type A struct {
i int
}
func (a *A) Set(i int) {
a.i = i
}
func TestInherit(t *testing.T) {
var a = A{3}
a.Set(4)
t.Log(a.i) // 输出 4
}
这里可以通过非指针的 a 调用 Set 函数,并且 Set 的值是有效地。
第一个疑问:go 在调用方法时,会先将接收器的值复制一份,然后在这个副本上执行方法。我的理解是 a 复制了一份,在新的 a 上面修改不应该影响原来的 a 。
type Set interface {
Set(int)
}
type A struct {
i int
}
func (a *A) Set(i int) {
a.i = i
}
func TestInherit(t *testing.T) {
var _ Set = A{} // 这里编译不通过,提示没有实现 Set 方法。
}
第二个疑问,为啥上面的例子能调用 a.Set(),为啥这里又报错说没有实现 Set 方法。
1
SuperMild 2021-03-23 21:38:13 +08:00
https://tour.golang.org/methods/6
That is, as a convenience, Go interprets the statement v.Scale(5) as (&v).Scale(5) since the Scale method has a pointer receiver. |
2
thefack 2021-03-23 21:41:32 +08:00
第一个问题是编译器给你补充了引用:`&a.Set(4)`
第二个问题对照第一个问题,实现 Set 的是 &A,不是 A,所以报错 |
3
linvon 2021-03-23 21:43:15 +08:00
一:如果是值接收器确实是做一次值拷贝,但你这个方法是指针接收器,go 会对 a 做取地址,在执行指针接收器的方法,就会修改值
二:Set 方法实现的是指针接收器,A{}是一个值类型,并没有实现 Set 方法 可以去搜一下 go 的值接收器和指针接收器区别 |
4
kiripeng 2021-03-23 21:52:40 +08:00
type A struct {
i int } func (a *A) Set(i int) { a.i = i } 等于 func Set(a *A,i int) 这个准确来说是实现了指针形式的方法集 如果不用指针 var _ Set =&A{}而是使用 var _ Set =A{} 就会出现这个问题就是了,因为这时候是去 A 找实现了非地址值的方法集,然后找不到,可惜的是对于 golang 来说我觉得他限制了地址值和非地址值嵌入只能一种最大的目的应该是防止出现用到后面会出事,不知道哪个是哪个,防止地址值的方法集和非地址值的方法集混淆。 var _ Set =A{} 如果要行得通就是 func (a A) Set(i int) { a.i = i } func (a *A) Set(i int) { a.i = i } 而对于这个,a.set 其实就是转化成 (&a,)了,这个你可以试下如果实现的是 func (a A) Set(i int) { a.i = i } 用空指针去调用他就会爆出 main.(*A).Set(...) |
5
keepeye 2021-03-23 22:00:33 +08:00
第一个是值拷贝没错,但是调方法的时候隐式转换成指针接收了,但不能说 a 实现了 Set 接口。。所以还是代码不规范的问题,正常因该不会这么写
|
6
george404 2021-03-24 07:09:54 +08:00
试试看
``` func (a *A) Set(i int) { a.i = i } ``` 改成 ``` func (a *A) Set(i int) { a.i = i } ``` 你看看你还能修改值了 |
7
love2020 2021-03-24 08:31:00 +08:00
为什么不先看教程。。。
|
9
ly020044 2021-03-24 08:41:12 +08:00
哎呀我的大宝贝,为啥不先看一下教程?好好看一下指针吧
|
10
dong568789 2021-03-24 10:04:26 +08:00
6 楼在说啥?
|
11
zjj19950716 2021-03-24 20:09:14 +08:00
|
12
george404 2021-03-25 06:54:35 +08:00
@dong568789 擦,忘了吧第二个的*A 的指针去掉。。。。
|