- 收者是 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)