This is a creation in Article, where the information may have evolved or changed.
Variables of value type and pointer types
Declare a struct first:
type T struct { Name string}func (t T) M1() { t.Name = "name1"}func (t *T) M2() { t.Name = "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 variable of type T 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:
Before M1 call: T1
After M1 call: T1
Before M2 call: T1
After M2 call: 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 calling T1. M1 () is equivalent to M1 (T1), and both the argument and the row parameter are of type T, which is acceptable. 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 calling T1. M2 () = M2 (T1), which is to pass the T type to the *t type, go may take the T1 address into it: M2 (&T1). So the modification of M2 () can affect T1.
- Types of variables are owned by both methods.
The following declares a variable of type *t 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:
Before M1 call: T2
After M1 call: T2
Before M2 call: T2
After M2 call: 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), which are pointer types and do 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 (type T) as type Intf in assignment:
T does not implement Intf (M2 method has pointer receiver)
var t2 Intf = T1 this line error.
T1 is a M2 () method, but why is it not passed on to T2 simultaneous?
Simply put, according to the theory of the interface: Pass the "assignment" of the object must implement the interface requirements of the method, and T1 did not implement M2 (), T1 pointer implementation M2 (). In addition, like the C language, the function name itself is the pointer
When the var t2 Intf = T1 modified to var t2 Intf = &t1 when compiled through, at this time T2 get T1 address, T2. The modification of M2 () can affect the T1.
If you declare a method func F (t Intf), the arguments are passed in the same manner 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:
Before M1 call: T1
After M1 call: T1
Before M2 call: T1
After M2 call: name2
T1
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 () is equivalent to M1 (T1) instead of M1 (s).
The last T1 value does not change, because we embed the T type, so s{t1} is a copy of the T1.
What if we assign S to the Intf interface?
var intf Intf = s intf.M1() intf.M2()
Error:
Cannot use S (Type S) as type Intf in assignment:s does not implement Intf (M2 method has pointer receiver)
is still a problem with M2 () because S is still a value type at this time.
var intf intf = &s Such words are compiled through, if at intf. M2 () changed the value of Name, S.name was changed, but T1. The Name remains the same, because now T1 and s are no longer connected.
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)
Before M1 call: T1
After M1 call: T1
Before M2 call: T1
After M2 call: name2
Name2
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 i ntf.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 effect is the same as above.