arrays - 在 Go 中传入值或将地址传入接口有什么区别?
问题描述
假设我们有一个简单的接口和实现:
type Vertex struct {
X int
Y int
}
type Abser interface {
Abs() float64
}
func (v Vertex) Abs() float64 {
sum := float64(v.X + v.Y)
return math.Sqrt(sum)
}
现在我有一个接口变量:
var abser Abser
我想为它设置一个顶点。我可以设置一个的值,或者一个的地址:
v := Vertex{1, 1}
abser = v
abser = &v
两者有什么区别?为什么设置Vertex的地址有效?这与接口如何在幕后工作有什么关系?我对 Go 还是很陌生,所以非常感谢任何帮助
解决方案
在 Go 类型系统中,为 和 定义了一个使用类型值接收器T
定义的方法T
,*T
即:
func (v Vertex) Abs() float64 {...}
这适用于v
和*v
。方法本身总是接收v
.
定义为的方法*T
仅定义为*T
而不是为T
。那是:
func (v *Vertex) SetX(newx float64) {v.X=newx}
该方法SetX
仅在接收器可寻址时才有效。这是必要的,这样您就不会编写丢失数据的代码。例如:
m:=map[string]Vertex{}
m["a"]=Vertex{}
m["a"].SetX(1) // This fails! m["a"] is not addressable
如果上述情况没有失败,那么SetX
会设置 的副本m["a"]
,并且效果会丢失,因为更新的副本没有放回地图中。
回到接口:你的Abser
接口是由任何实现的类型实现的Abs() float64
。基于以上讨论,两者Vertex
都*Vertex
实现Abser
.
假设您定义Vertex.Abs
为:
func (v *Vertex) Abs() float64 {...}
然后,只*Vertex
实现Abser
,所以:
abser = v // This would fail
abser = &v // This would work
推荐阅读
- c# - 如何设置实体框架核心连接超时?
- python - 使用 python 排列 output.txt?
- r - 使用 betapart 和 ddecay 包的距离衰减错误
- arrays - VBA - 如何创建水平二维数组
- java - 在java中获得字符串排列的有效/快速方法
- r - 为什么 unlist() 将字符串列表转换为数字?
- laravel - Laravel Telegram bot 错误请求:字符串必须以 UTF-8 编码
- python - 如何解决 PyFMI 中的字符编码错误?
- php - 在 prestashop 1.6 中无法使用 address->id_country 加载国家/地区
- python - pdfQuery 结果数据的面向对象数据结构是什么?