当前位置:网站首页>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)
边栏推荐
猜你喜欢
随机推荐
MySQL Checking and Filling Leaks (5) Unfamiliar Knowledge Points
4.字符流
Redis high availability
Domestic Google earth, terrain analysis seconds kill with the map software
.ts 音频文件转换成 .mp3 文件
TypeScript Brief (1)
列表
Domestic with Google earth software, see the download 19th level high-resolution satellite images so easy!
网络安全入门基础:IP地址
第四讲 SVN
Read file by byte and character_load configuration file
选择黑盒测试用例设计方法的综合策略方案总结
6.File类
【个人学习总结】CRC校验原理及实现
4.泛型和工具类
Ontology Development Diary 03-Understanding Code
全网最全的软件测试基础知识整理(新手入门必学)
Understanding of PID control motor output as motor PWM duty cycle input
本体开发日记04-努力理解protege的某个方面
div模拟textarea文本框,输入文字高度自适应,且实现字数统计和限制