代码1:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
//func GotU(t esc);
func (e esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(test)
fmt.Println(test.i)
}
代码2:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
func (e esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(&test)
fmt.Println(test.i)
}
代码3:
package main
import "fmt"
type myintf interface {
GotU()
}
type esc struct {
i int
}
func (e *esc)GotU() {
e.i = 10
}
func TestFunc(it myintf) string {
it.GotU()
return "kk"
}
func main() {
var test esc
test.i = 9
TestFunc(test)
fmt.Println(test.i)
}
由于仅实现了func (e esc)GotU()
,为什么这两段代码都应该工作并产生相同的结果?
将结构的指针传递给该函数(TestFunc)以获得相同的答案,这让我感到困惑。
答案 0 :(得分:1)
最后一个代码段实现了指针类型的方法接收器。如果要修改接收器的值,将考虑这种情况。
func (e *esc) GotU() {
e.i = 10
}
在上述情况下,由于您要在实现接口的方法上传递指针类型的接收器。
type myintf interface {
GotU()
}
因此,您需要在TestFunc
中传递struct的地址。这就是您收到类型不匹配错误的原因,因为您传递的是esc
类型的变量,而方法需要*esc
的变量。
func main() {
var test esc
test.i = 9
TestFunc(&test)
fmt.Println(test.i)
}
在Go playground上的工作示例
在Golang中,有两种方法可以传递方法接收器。
func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct) valueMethod() { } // method on value
对于不习惯使用指针的程序员,两者之间的区别 这两个例子可能令人困惑,但实际情况是 很简单的。在类型上定义方法时,接收方( 上面的示例)的行为就好像它是 方法。将接收器定义为值还是指针是 那么,同样的问题,如函数参数是否应为 值或指针。有几个注意事项
首先,也是最重要的一点,该方法是否需要修改接收器?如果是这样,则接收者必须是指针。 (切片和地图用作参考,因此它们的故事有些微妙,但是例如,要更改方法中切片的长度,接收者必须仍然是指针。)在上面的示例中,如果pointerMethod修改了s,调用者将看到这些更改,但是valueMethod是通过调用者参数的副本(即传递值的定义)进行调用的,因此,所做的更改对于调用者而言将是不可见的。
答案 1 :(得分:1)
第一个版本和第二个版本之间的区别在于,您直接在一个版本中传递结构,而在另一个版本中传递指向结构的指针。在这种情况下,这些程序的工作原理相同,因为指针还包括该结构上所有已定义的函数。
但是,这反过来是行不通的。您在指针接收器上定义方法GotU
。该结构不了解此功能。如果您愿意打电话
TestFunc(&test)
在第三个程序中,它将编译,但工作方式与其他两个程序不同:输出为:“ 10”
由于在指针接收器上定义了GotU
,test
被作为引用传递,并且修改持续存在。在其他程序中,test
作为值传递,即将其复制,并在GotU
中修改副本。当func退出时,副本将被丢弃,并且旧版本仍与以前相同。