This is a creation in Article, where the information may have evolved or changed.
Reference article: http://studygolang.com/articles/1113
The following issues are expected to be resolved
Suppose there are two methods, the recipient of a method is a pointer type, and the recipient of a method is a value type, then:
- What is the difference between these two methods for variables of value types and for variables of pointer types?
- If these two methods are intended to implement an interface, can both methods be called?
- If the method is embedded in other structures, what are the above two things?
Variables of value type and pointer types
Declare a struct first:
typestruct { string}func (t T) M1() { "name1"}func (t *T) M2() { "name2"}
The recipient of M1 () is a value type T, the recipient of M2 () is a value type *t, and two methods change the name value.
The following declares a T
variable of type and calls M1()
and M2()
.
t1 := T{"t1"} fmt.Println("M1调用前:", t1.Name) t1.M1() fmt.Println("M1调用后:", t1.Name) fmt.Println("M2调用前:", t1.Name) t1.M2() fmt.Println("M2调用后:", t1.Name)
The output is:
M1调用前: t1M1调用后: t1M2调用前: t1M2调用后: name2
Let's guess what go will do with it.
Let's make a pact: the receiver can be thought of as the first parameter of the function, that is: func M1(t T)
func M2(t *T)
Go is not an object-oriented language, so it may be biased to understand that it looks like object-oriented syntax.
When called t1.M1()
, the M1(t1)
argument and the row parameter are both type T and can be accepted. At this point the T in M1 () is only a copy of the value of T1, so the modification of M1 () does not affect T1.
When called t1.M2()
= = M2(t1)
, this is the type of T passed to the *t type, go may take T1 address to pass in: M2(&t1)
. So the modification of M2 () can affect T1.
Variables of type T are owned by both methods.
The following declares a *T
variable of type and calls M1()
and M2()
.
t2 := &T{"t2"} fmt.Println("M1调用前:", t2.Name) t2.M1() fmt.Println("M1调用后:", t2.Name) fmt.Println("M2调用前:", t2.Name) t2.M2() fmt.Println("M2调用后:", t2.Name)
The output is:
M1调用前: t2M1调用后: t2M2调用前: t2M2调用后: name2
t2.M1()
= = M1(t2)
, t2 is the pointer type, takes the value of T2 and copies a copy to M1.
t2.M2()
= = M2(t2)
is a pointer type and does not need to be converted.
Variables of type *t are also owned by these two methods.
What happens when I pass it to the interface?
Declare an interface first
type Intf interface { M1() M2()}
Use:
var t1 T = T{"t1"} t1.M1() t1.M2() var t2 Intf = t1 t2.M1() t2.M2()
Error:
./main.go:9: cannot use t1 (typeastypein assignment: notmethod has pointer receiver)
var t2 Intf = t1
This line is an error.
T1 is a M2 () method, but why is it not passed on to T2 simultaneous?
T1 is a value type, assigning a value to T2 is a copy of a value instead of a pointer, assuming T1 can be assigned to T2, T2. M2 () Modify the value of Name is also a modified copy of the variable, can not affect the T1, that T1 assigned to T2 What is the point? So this assignment is not allowed.
When the var t2 Intf = t1
modification to var t2 Intf = &t1
compile through, at this time T2 obtained is the address of T1, t2.M2()
the modification can affect the T1.
If you declare a method, the pass of the func f(t Intf)
parameter is the same as the direct assignment above.
Nested types
Declare a type S, embed T in
type S struct { T}
Use the following example to test:
t1 := T{"t1"} s := S{t1} fmt.Println("M1调用前:", s.Name) s.M1() fmt.Println("M1调用后:", s.Name) fmt.Println("M2调用前:", s.Name) s.M2() fmt.Println("M2调用后:", s.Name) fmt.Println(t1.Name)
Output:
M1调用前: t1M1调用后: t1M2调用前: t1M2调用后: name2t1
If T is embedded in S, then the methods and properties that T owns are also owned, but the receiver is not s but T.
So s.M1()
it M1(t1)
's equivalent instead of M1(s)
.
The last T1 value does not change, because we embed the T type, so S{t1}
the time is to copy the T1 copies.
What if we assign S to the Intf interface?
var intf Intf = s intf.M1() intf.M2()
Error:
cannot use s (typeastypein assignment: notmethod has pointer receiver)
is still a problem with M2 () because S is still a value type at this time.
var intf Intf = &s
So the compiler passed, if the intf.M2()
value changed in the Name, s.Name
was changed, but t1.Name
still unchanged, because now T1 and S have no contact.
Try embedding *t below:
type S struct { *T}
When using this:
t1 := T{"t1"} s := S{&t1} fmt.Println("M1调用前:", s.Name) s.M1() fmt.Println("M1调用后:", s.Name) fmt.Println("M2调用前:", s.Name) s.M2() fmt.Println("M2调用后:", s.Name) fmt.Println(t1.Name)
The only difference is that the value of the last T1 is changed, because we are copying pointers.
Then assign the value to the interface to try:
var intf Intf = s intf.M1() intf.M2() fmt.Println(s.Name)
Compile without error. What we pass to intf here is the value type instead of the pointer, why can we pass it?
When you copy S, T is the pointer type, so when you call M2 (), you pass in a pointer.
var intf Intf = &s
The effect is the same as above.