接收者的使用
package main
import "fmt"
type Person struct {
name string
age int
}
func (p *Person) greeting1() {
fmt.Println(p) //&{0}
fmt.Println(&p) //0xc000086018
fmt.Println("Hello~")
}
func (p Person) greeting2() {
fmt.Println(p) //{0}
fmt.Println(&p) //&{0}
fmt.Println("Hello~")
}
type Student struct {
//p Persion -> has a
Person // -> is a
school string
grade int
}
func test1(p Student) {
fmt.Println(p)
}
func test2(p *Student){
fmt.Println(p)
}
func main() {
var s Student
//s.p.greeting()
s.greeting1()
s.greeting2()
test1(s)
//test2(s) -> error
}
当我在 golang 中使用函数时,如果我声明值变量,当我使用我创建的函数时,我必须只将值变量放在参数上。喜欢,
a int= 10;
func func1(param int){
fmt.Println(fmt)
}
尽管我在 Student 结构中将 Person 声明为值结构, 正如你看到我的代码, 接收函数 (greeting1, greeting2) 正在获取两个类型参数,即 *Person 和 Person。 我无法理解为什么 greeting1 函数可以正常运行,尽管我将值变量作为参数。 谢谢你们的帮助。
最佳答案
简化您的示例代码以专注于手头的问题:
package main
import "fmt"
type Person struct {
name string
age int
}
func (p *Person) greeting1() {
fmt.Println(p)
fmt.Println(&p)
}
func main() {
var p Person
p.name = "joe"
p.age = 41
p.greeting1()
}
打印:
&{joe 41}
0xc00000c028
简而言之,调用 p.greeting1()
是有效的,因为 Go 看到 Person
(p
的类型)有一个 greeting1
指针接收器上定义的方法。因此它将调用 p.greeting1()
视为等同于 (&p).greeting1()
。正如 mkopriva 在评论中所说,这在 Go spec 中有明确规定。 :
A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()
这样做是为了方便。由于指针接收器在 Go 中是非常必要和流行的——每当你的方法改变底层对象时你都需要它们——它有助于编写更清晰的代码。您不应该被迫在 p.greeting1()
会做的地方编写 (&p).greeting1()
- 这种替换是明确的,因为编译器知道定义了哪些方法在 Person
上,以及与哪些接收者。
Effective Go 在 pointer vs. value receivers 上有一节你应该阅读。这是一个相关的引用:
When the value is addressable, the language takes care of the common case of invoking a pointer method on a value by inserting the address operator automatically. In our example, the variable b is addressable, so we can call its Write method with just b.Write. The compiler will rewrite that to (&b).Write for us.
关于go - go中receiver使用struct的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54275543/