当前位置:网站首页>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)
原网站

版权声明
本文为[草明]所创,转载请带上原文链接,感谢
https://blog.csdn.net/galoiszhou/article/details/122704441