简体   繁体   中英

Difference between a method receiver as pointer or not

Why don't I have to define PrintValue() as a pointer receiver (*One) to be able to print "hello"?

package main
import "fmt"


type One struct{
    a string
}
func (o *One)AssignValue(){
    o.a = "hello"
}
func (o One)PrintValue(){
    fmt.Println(o.a)
}

func main() {
    one := One{}
    one.AssignValue()
    one.PrintValue()
}

Because one is already of type One . The instantiation syntax

t := One{}

creates a value of type One while the form

p := &One{}

creates a pointer to a value of type One .

This means that nothing is to be done when calling t.PrintValue as the receiver type ( One ) is already the same as the type of t ( One as well).

When calling p.PrintValue the compiler automatically converts an addressable variable to its pointer form because the receiver type ( One ) is not equal to the type of p ( *One ). So the expression

p.PrintValue()

is converted to

(*p).PrintValue()

There is also a conversion necessary when calling t.AssignValue as this method has a pointer receiver but we're supplying a value. This is also done automatically by the compiler where possible.

From the spec on calls :

A method call xm() 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, xm() is shorthand for (&x).m()

This means the expression

t.AssignValue()

is converted to

(&t).AssignValue()

Note that this is not always possible. For example when returning a value from a function:

func NewOne(s string) One { return One{s} }

NewOne("foo").AssignValue() // Not possible

x := NewOne("foo")
x.AssignValue() // Possible, automatically converted

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM