golang 接口变量的赋值和方法的调用
1、「方法」概念介绍
带有接收者的函数称为方法,方法是 go 语言中一种替代面向对象的方式。函数内部可以使用接收者,使用完之后根据接收者的类型是值类型还是指针类型选择是否自动覆盖原接收者。
可以随意安排函数定义的顺序,编译器会在执行前扫描每个文件。
2、接口变量的赋值
接口定义为一个方法的集合。方法包含实际的代码。换句话说,一个接口就是定义, 而方法就是实现。因此,接收者不能定义为接口类型,这样做的话会引起 invalid receiver type ... 的编译器错误。
接收者类型必须是 T 或 *T,这里的 T 是类型名。T 叫做接收者基础类型或 简称基础类型。
如果接收者是实现了接口定义申明的所有方法,那么称这个接收者实现了这个接口。
2.1 方法的接收者是值类型
当方法的接收者是值类型时,接口变量可以被赋值为指针类型或者值类型的接收者对象
package main import ( "fmt" ) type Producer interface { send(string) error } type KafkaProducer struct { topic string name string } // 接收者是值类型 func (s KafkaProducer) send(msg string) error { fmt.Printf("send %s to topic [%s] ", msg, s.topic) return nil } func main() { var producer Producer kafkaProducer := KafkaProducer{"like_topic", "kafkaProducer"} producer = kafkaProducer fmt.Printf("%T, %#v ", producer, producer) // main.KafkaProducer, main.KafkaProducer{topic:"like_topic", name:"kafkaProducer"} producer.send("hahha") // send hahha to topic [like_topic] producer = &kafkaProducer fmt.Printf("%T, %#v ", producer, producer) // *main.KafkaProducer, &main.KafkaProducer{topic:"like_topic", name:"kafkaProducer"} producer.send("hahha") // send hahha to topic [like_topic] }
2.2 方法的接收者是指针(引用)类型
当接收者是指针类型时,接口变量只能被赋值为指针类型的接收者对象,如果被赋值为了值类型的接收者对象,会有类似下面程序的报错Cannot use 'rocketProducer' (type RocketProducer) as the type Producer Type does not implement 'Producer' as the 'send' method has a pointer receiver
package main import ( "fmt" ) type Producer interface { send(string) error } type RocketProducer struct { topic string name string } // 接收者是指针类型 func (s *RocketProducer) send(msg string) error { fmt.Printf("send %s to topic [%s] ", msg, s.topic) return nil } func main() { var producer Producer rocketProducer := RocketProducer{"collection_topic","rocketProducer"} producer = rocketProducer // Cannot use 'rocketProducer' (type RocketProducer) as the type Producer Type does not implement 'Producer' as the 'send' method has a pointer receiver fmt.Sprintf("%T, %#v ", producer, producer) producer = &rocketProducer fmt.Printf("%T, %#v ", producer, producer) // *main.RocketProducer, &main.RocketProducer{topic:"collection_topic", name:"rocketProducer"} producer.send("hahha") // send hahha to topic [collection_topic] }
2.3 对象没有实现接口
如果对象没有实现接口的方法,那么不能被赋值给接口变量,否则会有类似如下程序的报错Cannot use 'rabbitProducer' (type RabbitProducer) as the type Producer Type does not implement 'Producer' as some methods are missing: send(string) error
package main import ( "fmt" ) type Producer interface { send(string) error } type RabbitProducer struct { topic string name string } func main() { var producer Producer rabbitProducer := RabbitProducer{"share_topic", "rabbitProducer"} producer = rabbitProducer // Cannot use 'rabbitProducer' (type RabbitProducer) as the type Producer Type does not implement 'Producer' as some methods are missing: send(string) error }
3、方法调用
接收者是指针则在方法修改对象的属性会影响原来的对象,如果接收者是对象,那么在方法中修改对象的属性不会影响原来的对象。跟上面的接口变量赋值略有不同,不管方法里的接收者是指针类型还是对象类型,都可以同时使用指针对象和值对象调用。golang 通过语法糖,使得值对象也能直接调用接收者为指针类型的方法。
package main import "fmt" type KafkaProducer struct { topic string name string } // 接收者是值类型 func (s KafkaProducer) updateName(newName string) error { s.name = newName return nil } type RocketProducer struct { topic string name string } // 接收者是指针类型 func (s *RocketProducer) updateName(newName string) error { s.name = newName return nil } func main() { kafkaProducer1 := KafkaProducer{"like_topic", "kafkaProducer"} kafkaProducer1.updateName("aaa") fmt.Printf("kafkaProducer1.name = %v ", kafkaProducer1.name) kafkaProducer2 := &KafkaProducer{"like_topic", "kafkaProducer"} kafkaProducer2.updateName("bbb") fmt.Printf("kafkaProducer2.name = %v ", kafkaProducer2.name) rocketProducer1 := RocketProducer{"collection_topic","rocketProducer"} rocketProducer1.updateName("aaa") fmt.Printf("rocketProducer1.name = %v ", rocketProducer1.name) rocketProducer2 := &RocketProducer{"collection_topic","rocketProducer"} rocketProducer2.updateName("bbb") fmt.Printf("rocketProducer2.name = %v ", rocketProducer2.name) }
输出
kafkaProducer1.name = kafkaProducer kafkaProducer2.name = kafkaProducer rocketProducer1.name = aaa rocketProducer2.name = bbb
相关文章
- 【Docker 系列】docker 学习六,DockerFile
- 【Docker 系列】docker 学习八,Docker 网络
- 【Docker 系列】docker 学习九,Compose 内容编排官网初步体验
- 【Docker 系列】docker 学习十,Compose 编写规则及wp 实战
- 【Docker 系列】docker 学习十一,docker 总结和面试题整理
- 【K8S 系列】k8s 学习一,Kubernetes 基本介绍及核心组件
- Verilog HDL基本语法规则
- 【K8S 系列】k8s 学习二,kubernetes 核心概念及初步了解安装部署方式
- Verilog HDL门级建模
- Verilog HDL数据流建模与运算符
- Verilog HDL行为级建模
- 什么是禅道?禅道可以做什么?如何自动推送禅道消息?
- composer self-update 更新版本
- CGO学习二,基本数据类型转换2 和 函数调用
- SSH连接服务器后执行多条命令
- Go test 单元测试用起来
- 那些你不知道的 goland 技巧
- 听说你还在自己做重复劳动?看我一键生成错误码映射
- 原来服务端的退出姿势也可以这么优雅
- 你以为传切片就是传引用了吗?