dongtuojuan8998 2019-01-20 10:31
浏览 52

接收器在struct中使用struct的问题

receiver's usage

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 
}

When I use function in golang, If I declare value variable, when I use function I made, I had to put only value variable on paramter. like,

a int= 10;
func func1(param int){
 fmt.Println(fmt)
}

despite I declared Person as a value struct in Student struct, as you see my code, receiver functions(greeting1, greeting2) are getting two type parameters which are *Person, and Person. I cannot understand that why greeting1 function is functioning without error, despite I put value variable as a parameter. Thank you for you guys help.

  • 写回答

2条回答 默认 最新

  • dtiu94034 2019-01-20 14:19
    关注

    Simplifying your example code to focus on the question / issue at hand:

    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()
    }
    

    Prints:

    &{joe 41}
    0xc00000c028
    

    In short, the call p.greeting1() works because Go sees that Person (the type of p) has a greeting1 method defined on a pointer receiver. So it treats the call p.greeting1() as equivalent to (&p).greeting1(). As mkopriva said in a comment, this is clearly laid out in the 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()

    This is done for convenience. Since pointer receivers are quite necessary and popular in Go - you need them whenever your method mutates the underlying object - it helps write cleaner code. You shouldn't be forced to write (&p).greeting1() where p.greeting1() would do - this substituion is unambiguous as the compiler knows what methods are defined on Person, and with which receivers.

    Effective Go has a section on pointer vs. value receivers that you should read. Here's one relevant quote:

    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.

    评论

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题