指針方法
特點
指針方法複製源值的指針並以指針參數的形式傳入函數中,函數中對指針參數內容的修改即爲源值內容的修改,所以會全部反應到源值上。
可對照 輸出: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 ↩︎