go - go中receiver使用struct的问题

标签 go receiver

接收者的使用

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/

相关文章:

android - 致命异常 : java. lang.IllegalArgumentException : Receiver not registered: android. hardware.camera2.CameraManager

android - 更新从广播接收器收到的短信的 Activity 用户界面

android - 什么是 'action android:name="com.android.vending.INSTALL_REFERRER"'?

go - 困惑 : implement multiple interfaces in Go

android - 启动接收器在模拟器中不工作

postgresql - 转到 time.Time 到 postgresql timestamptz 无法使用 time.Now() 保存

戈朗,围棋 : mapping with returning interface?

android - 格式错误的 android list 违反条款

http - 如何将 CAFile 添加到我们的证书中

go - 逃逸分析之前的变量生命周期是什么?