指针方法
特点
指针方法复制源值的指针并以指针参数的形式传入函数中,函数中对指针参数内容的修改即为源值内容的修改,所以会全部反应到源值上。
可对照 输出:1 2 4 佐证。
值方法
特点
值方法会创建新变量以复制源值内容,并将该新变量以值参数的形式传入函数中, 所以函数中值参数是源值内容的复制,与源值再无联系,所以函数内值参数内容的修改不会反应到源值上。
可对照 输出:1 3 4 佐证。
特例
值方法对引用类型1源值的修改,会在源值上反应。
可对照 输出:6 7 8 deskmate[0] addr 佐证。原理:
切片类型指向底层数组,是对底层匿名数组的引用。
调用值方法时复制了原址内容的的值参数指向的仍是与源值相同的底层数组,
若不触发底层数组的扩容,则对值参数的所有修改都会反应到源值上。
当对值参数的改动触发底层数组扩容时,值参数指向扩容后的新数组,源值指向旧数组。
只有此时值参数和源值才真正独立互不影响。
代码
源码
package main
import "fmt"
type Student struct {
Age int
Name string
DeskMate []string
}
func (s *Student) SetAge(age int) {
s.Age = age
fmt.Printf("2 func SetAge:: addr: %p type: %T data: %+v \n", s, s, *s)
}
func (s Student) SetName(name string) {
s.Name = name
fmt.Printf("3 func SetName:: addr: %p %T data: %+v \n", &s, s, s)
}
func (s Student) ModifyDeskMate(deskMate string) {
s.DeskMate[0] = deskMate
fmt.Printf(
"7 func ModifyDeskMate:: deskmate addr: %p deskmate[0] addr: %p deskmate[0] data: %+v \n",
&s.DeskMate, &s.DeskMate[0], s.DeskMate[0])
}
func main() {
var s Student
fmt.Printf("1 func main:: addr: %p type: %T data: %+v \n", &s, s, s)
(&s).SetAge(12) // 完全等价于s.SetAge(12), 因为变量调用值方法/指针方法时, go内部会自动帮我们把变量转换为合适的类型
s.SetName("anne") // 完全等价于(&s).SetName("anne")
fmt.Printf("4 func main:: addr: %p type: %T data: %+v \n", &s, s, s)
fmt.Println("----------------------special case----------------------")
s.DeskMate = []string{"barry", "charles"}
fmt.Printf("5 func main:: addr: %p type: %T data: %+v \n", &s, s, s)
fmt.Printf(
"6 func main:: deskmate addr: %p deskmate[0] addr: %p deskmate[0] data: %+v \n",
&s.DeskMate, &s.DeskMate[0], s.DeskMate[0])
s.ModifyDeskMate("anduin")
fmt.Printf(
"8 func main:: deskmate addr: %p deskmate[0] addr: %p deskmate[0] data: %+v \n",
&s.DeskMate, &s.DeskMate[0], s.DeskMate[0])
fmt.Printf("9 func main:: addr: %p type: %T data: %+v \n", &s, s, s)
}
输出
1 func main:: addr: 0xc000060150 type: main.Student data: {Age:0 Name: DeskMate:[]}
2 func SetAge:: addr: 0xc000060150 type: *main.Student data: {Age:12 Name: DeskMate:[]}
3 func SetName:: addr: 0xc000060210 main.Student data: {Age:12 Name:anne DeskMate:[]}
4 func main:: addr: 0xc000060150 type: main.Student data: {Age:12 Name: DeskMate:[]}
----------------------special case----------------------
5 func main:: addr: 0xc000060150 type: main.Student data: {Age:12 Name: DeskMate:[barry charles]}
6 func main:: deskmate addr: 0xc000060168 deskmate[0] addr: 0xc00000c080 deskmate[0] data: barry
7 func ModifyDeskMate:: deskmate addr: 0xc000060378 deskmate[0] addr: 0xc00000c080 deskmate[0] data: anduin
8 func main:: deskmate addr: 0xc000060168 deskmate[0] addr: 0xc00000c080 deskmate[0] data: anduin
9 func main:: addr: 0xc000060150 type: main.Student data: {Age:12 Name: DeskMate:[anduin charles]}
常见引用类型: slice, map, channel
常见值类型: int, float, bool, string, array ↩︎