当前位置:网站首页>Go-接口的那些事
Go-接口的那些事
2022-08-09 09:27:00 【草明】
- 收者是 T
- 成员方法/属性的调用者可以是 T 和 *T
- 接口的动态类型可以是 T 和 *T
- 接收者是 *T
- 成员方法/属性的调用者可以是 T 和 *T
- 接口的动态类型可以只能是 *T
- 接口的动态类型是 nil, 接口不是nil
- 接口的动态类型是 nil, 不可以调用动态类型的属性, 单可以调用动态类型的方法(调用的过程中, 不能调用动态类型的属性)
上代码, 自己品
package main
import "fmt"
type Pet interface {
Name() string
}
type Dog struct {
name string
}
func (self Dog) SetName(name string) {
self.name = name
}
func (self Dog) Name() string {
return self.name
}
func main() {
//接收者是 T
dog := &Dog{
"Max"}
// 成员方法/属性的调用者可以是 T 和 *T
fmt.Println((*dog).Name())
fmt.Println(dog.Name())
fmt.Println((*dog).name)
fmt.Println(dog.name)
// 接口的动态类型可以是 T 和 *T
var pet Pet = *dog
fmt.Println(pet.Name())
var pet2 Pet = dog
fmt.Println(pet2.Name())
}
package main
import "fmt"
type Pet interface {
Name() string
}
type Dog struct {
name string
}
func (self *Dog) SetName(name string) {
self.name = name
}
func (self *Dog) Name() string {
return self.name
}
func main() {
//接收者是 *T
dog := &Dog{
"Max"}
// 成员方法调用者可以是 T 和 *T
fmt.Println((*dog).Name())
fmt.Println(dog.Name())
fmt.Println((*dog).name)
fmt.Println(dog.name)
// 接口的动态类型可以只能是 *T
// Error: Cannot use '*dog' (type Dog) as type Pet Type does not implement 'Pet' as 'Name' method has a pointer receiver
//var pet Pet = dog
var pet2 Pet = dog
fmt.Println(pet2.Name())
}
package main
import "fmt"
type Pet interface {
Name() string
}
type Dog struct {
name string
}
func (self Dog) SetName(name string) {
self.name = name // 此处是副本, 无法改变外面的
}
func (self Dog) Name() string {
return self.name
}
func main() {
//接收者是 T
dog := &Dog{
"Max"}
(*dog).SetName("Bear")
fmt.Println("dog name:", (*dog).Name()) // Max
fmt.Println("dog name:", dog.Name()) // Max
dog.SetName("Bear")
fmt.Println("dog name:", dog.Name()) // Max
var pet Pet = *dog
dog.SetName("Bear")
fmt.Println("dog name:", dog.Name()) // Max
fmt.Println("pet name:", pet.Name()) // Max
var pet2 Pet = dog
dog.SetName("Bear")
fmt.Println("dog name:", dog.Name()) // Max
fmt.Println("pet2 name:", pet2.Name()) // Max
// pet 包含的是 T 的副本, 所以 pet 的 name 没有改变
// pet2 包含的是 *T 的副本(指向的是同一个 T), 所以 pet2 的 name 改变了
dog.name="Bear"
fmt.Printf("dog: %v, name: %s\n", &dog, dog.Name()) // 0xc000124018, Bear
fmt.Printf("pet: %v, name: %s\n", &pet, pet.Name()) // 0xc00010c250, Max
fmt.Printf("pet2: %v, name: %s\n", &pet2, pet2.Name()) // 0xc00010c290, Bear
}
package main
import "fmt"
type Pet interface {
Name() string
}
type Dog struct {
name string
}
func (self Dog) SetName(name string) {
(&self).name = name // 此处是副本的指针, 无法改变外面的
}
func (self Dog) Name() string {
return self.name
}
func main() {
//接收者是 T
dog := &Dog{
"Max"}
(*dog).SetName("Bear")
fmt.Println("dog name:", dog.Name()) // Max
fmt.Println("dog name:", (*dog).Name()) // Max
dog.SetName("Bear")
fmt.Println("dog name:", dog.Name()) // Max
fmt.Println("dog name:", dog.name) // Max
var pet Pet = *dog
dog.SetName("Bear")
fmt.Println("dog name:", dog.Name()) // Max
fmt.Println("pet name:", pet.Name()) // Max
var pet2 Pet = dog
dog.SetName("Bear")
fmt.Println("dog name:", dog.Name()) // Max
fmt.Println("pet name:", pet2.Name()) // Max
dog.name="Bear"
fmt.Printf("dog: %v, name: %s\n", dog, dog.Name()) // 0xc0000ac018, Bear
fmt.Printf("pet: %v, name: %s\n", &pet, pet.Name()) // 0xc000096250, Max
fmt.Printf("pet2: %v, name: %s\n", &pet2, pet2.Name()) // 0xc000096290, Bear
}
package main
import "fmt"
type Pet interface {
Name() string
}
type Dog struct {
name string
}
func (self *Dog) SetName(name string) {
self.name = name
}
func (self *Dog) Name() string {
return self.name
}
func main() {
//接收者是 *T
dog := &Dog{
"Max"}
dog.SetName("Bear")
fmt.Println("dog name:", dog.Name()) // Bear
dog.SetName("Cooper")
fmt.Println("dog name:", (*dog).Name()) // Cooper
fmt.Println("dog name:", dog.Name()) // Cooper
var pet Pet = dog
dog.SetName("Milo")
fmt.Printf("dog: %v, name: %s\n", &dog, dog.Name()) // 0xc00000e028, Milo
fmt.Printf("pet: %v, name: %s\n", &pet, pet.Name()) // 0xc000010270, Milo
dog.name = "Duke"
fmt.Printf("dog: %v, name: %s\n", &dog, dog.Name()) // 0xc00000e028, Duke
fmt.Printf("pet: %v, name: %s\n", &pet, pet.Name()) // 0xc000010270, Duke
}
package main
import "fmt"
type Pet interface {
Name() string
}
type Dog struct {
name string
}
func (self *Dog) SetName(name string) {
(*self).name = name
}
func (self *Dog) Name() string {
return self.name
}
func main() {
//接收者是 *T
dog := &Dog{
"Max"}
dog.SetName("Bear")
fmt.Println("dog name:", dog.Name()) // Bear
dog.SetName("Cooper")
fmt.Println("dog name:", (*dog).Name()) // Cooper
fmt.Println("dog name:", dog.Name()) // Cooper
var pet Pet = dog
dog.SetName("Milo")
fmt.Printf("dog: %v, name: %s\n", &dog, dog.Name()) // 0xc0000ac018, Milo
fmt.Printf("pet: %v, name: %s\n", &pet, pet.Name()) // 0xc000096250, Milo
dog.name = "Duke"
fmt.Printf("dog: %v, name: %s\n", &dog, dog.Name()) // 0xc0000ac018, Duke
fmt.Printf("pet: %v, name: %s\n", &pet, pet.Name()) // 0xc000096250, Duke
}
package main
import "fmt"
type Pet interface {
Name() string
}
type Dog struct {
name string
}
func (self *Dog) SetName(name string) {
(*self).name = name
}
func (self *Dog) Name() string {
return self.name
}
func main() {
var dog *Dog
fmt.Printf("%v, %v\n", &dog, dog) // 0xc00000e028, <nil>
dog2 := dog
if dog2 == nil {
fmt.Printf("nil: %v, %v\n", &dog2, dog2) // nil: 0xc00000e038, <nil>
} else {
fmt.Printf("not nil: %v, %v\n", &dog2, dog2)
}
// 因为 Pet 是接口, 所以 pet 是 iface 的实例, 包装了 dog2 的副本, pet 不是 nil, 但是它被包装的动态值是 nil
var pet Pet = dog
if pet == nil {
fmt.Printf("nil: %v, %v\n", &pet, pet)
} else {
fmt.Printf("not nil: %v, %v\n", &pet, pet) // not nil: 0xc000010230, <nil>
}
}
package main
import "fmt"
type Pet interface {
Name() string
Category() string
}
type Dog struct {
name string
}
func (self *Dog) SetName(name string) {
(*self).name = name
}
func (self *Dog) Name() string {
return self.name
}
func (self *Dog) Category() string {
return "Dog"
}
func main() {
var dog *Dog
fmt.Printf("%v, %v\n", &dog, dog) // 0xc00000e028, <nil>
// dog 是 nil, 接口的实例 pet 不是 nil
// pet 可以调用动态类型 Dog 的成员方法, 但是成员方法不可以使用接收者的属性
var pet Pet = dog
fmt.Println(pet.Category()) // Dog
fmt.Println(pet.Name()) // panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x108b900]
}
package main
import "fmt"
type Pet interface {
Name() string
Category() string
}
type Dog struct {
name string
}
func (self *Dog) SetName(name string) {
(*self).name = name
}
func (self *Dog) Name() string {
return self.Category()
}
func (self *Dog) Category() string {
return "Dog"
}
func main() {
var dog *Dog
fmt.Printf("%v, %v\n", &dog, dog) // 0xc00000e028, <nil>
// dog 是 nil, 接口的实例 pet 不是 nil
// pet 可以调用动态类型 Dog 的成员方法, 但是成员方法不可以使用接收者的属性, 可以调用接收者的方法, 但是所有的调用链中, 不可以包含接收者的属性
var pet Pet = dog
fmt.Println(pet.Category()) // Dog
fmt.Println(pet.Name()) // Dog
}
package main
type Pet interface {
Name() string
Category() string
}
type Dog struct {
name string
}
func (self *Dog) SetName(name string) {
(*self).name = name
}
func (self *Dog) Name() string {
return self.name
}
func (self *Dog) Category() string {
return "Dog"
}
// 一个类型只实现了接口部分的方法, 只要不当作接口的动态类型使用, 程序不会出错
// 如果是故意为之, 可以忽略
// 如果是想实现接口的, 只是遗漏/名称错误, 可以使用以下小技巧验证是否实现了某个接口
// 验证是否实现了某个接口
var _ Pet = (*Dog)(nil)
边栏推荐
猜你喜欢

Domestic Google earth, terrain analysis seconds kill with the map software

.ts 音频文件转换成 .mp3 文件

HD Satellite Map Browser
软件测试面试常见问题及答案(发散思维、接口、性能、概念、)

接口性能测试方案设计方法有哪些?要怎么去写?

Ontology Development Diary 01-Jena Configuration Environment Variables

Django实现对数据库数据增删改查(一)

.equals ==

米斗APP逆向分析

使用Protege4和CO-ODE工具构建OWL本体的实用指南-1.3版本(4.Building An OWL Ontology)
随机推荐
How much do you know about the mobile APP testing process specifications and methods?
Ontology development diary 02 - simple sparql query
软件测试流程包括哪些内容?测试方法有哪些?
Summary of steps and methods for installing and uninstalling test cases that you must read
本体开发日记05-努力理解SWRL(Usage Suggestions)
电脑硬件基础知识科普
命令行查询数据库
seata处理分布式事务
本体开发日记01-Jena配置环境变量
【机器学习】网络爬虫实战详解
自动化测试简历编写应该注意哪方面?有哪些技巧?
Command line query database
软件测试个人求职简历该怎么写,模板在这里
Django实现对数据库数据增删改查(一)
学习双向链表的心得与总结
8.Properties属性集合
Django实现对数据库数据增删改查(二)
软件测试面试思路技巧和方法分享,学到就是赚到
TypeScript Brief (1)
有返回值的函数