当前位置:网站首页>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)
边栏推荐
猜你喜欢

Django实现对数据库数据增删改查(一)
自动化测试简历编写应该注意哪方面?有哪些技巧?

字符串

Ontology Development Diary 01-Jena Configuration Environment Variables

秒拍app分析

The div simulates the textarea text box, the height of the input text is adaptive, and the word count and limit are implemented
软件测试分析流程及输出项包括哪些内容?
本体开发日记03-排错进行时
黑盒测试常见错误类型说明及解决方法有哪些?

Read file by byte and character_load configuration file
随机推荐
Summary of steps and methods for installing and uninstalling test cases that you must read
lateral view explode的另一种实现方式
白盒测试的概念、目的是什么?及主要方法有哪些?
RPC服务远程漏洞
软件测试面试常见问题及答案(发散思维、接口、性能、概念、)
Onnx - environment build 】 【 tensorrt
MySQL event_single event_timed loop event
The div simulates the textarea text box, the height of the input text is adaptive, and the word count and limit are implemented
【个人学习总结】CRC校验原理及实现
map去重代码实现
自动化测试框架有哪几种?搭建的思路是什么?一篇文章让你彻底了解自动化
MySQL transaction isolation
本体开发日记05-努力理解SWRL(RDF Concrete Syntax)
类 对象 属性 方法 类的成员
MVCC multi-version concurrency control
常用命令之思科常用基础配置
Environment build onnxruntime 】
接口开发规范及测试工具的使用
3.练习Thread
5.转换流