Go语言返回值为接口类型时,返回带&指针和不带&实例有什么区别?
Go语言返回接口时结构体实例加
&与不加的区别 核心差异源于Go的接口实现规则、值拷贝逻辑和可修改性三个维度,具体如下:
接口实现匹配规则差异
Go的接口实现有个默认规则:如果结构体的所有方法都是值接收者,那么值类型和对应的指针类型都自动实现了该接口;只要结构体有一个方法是指针接收者,就只有指针类型实现了该接口,值类型不会自动实现。
- 如果你写的
myService所有方法都是值接收者,那么加不加&都能正常编译,两种写法都满足Service接口的实现要求。 - 只要
myService存在任意一个指针接收者的方法,不加&直接返回结构体值实例时,编译器会直接抛出类型不匹配错误,提示myService没有实现Service接口。
运行时开销差异
- 不加
&返回结构体值实例时,会触发一次完整的结构体拷贝,结构体字段越多、体积越大,拷贝的性能开销就越高。 - 加
&返回指针实例时,只会拷贝一个指针(64位系统下仅8字节),性能开销几乎可以忽略,是绝大多数业务场景下的最优选择。
实例可修改性差异
- 不加
&返回的值实例,外部拿到接口后即使做类型断言,拿到的也是原始实例的拷贝,对这个拷贝的修改不会作用到原始实例(除非结构体内部包含slice、map、指针这类引用类型字段,修改这类字段内容会同步到原始实例)。 - 加
&返回的指针实例,外部类型断言后拿到的是原始实例的指针,对指针指向实例的修改会直接作用到原始实例本身。
示例代码验证
type Service interface { Do() error } type myService struct { repository repository.Repository } // 指针接收者方法,仅*myService实现Service接口 func (s *myService) Do() error { // 业务逻辑 return nil } func NewService(rep repository.Repository) Service { // 仅加&的写法合法,去掉&会编译报错 return &myService{ repository: rep } }
内容的提问来源于stack exchange,提问作者vidola
相关产品推荐
相关产品推荐

