Go的*
1.值傳遞與引用傳遞形象化理解:
引用傳值:相當于把燒餅串成一串,然后是有底座的,這個底座就相當于地址,這個地址對應的燒餅就相當于變量,這個地址對應的所有的變量都是一樣的;
值傳遞:各個燒餅都是平放的,新的燒餅只是復制了之前的燒餅,之后被吃了,或者被煮了,與最開始的燒餅無關了
傳地址進函數,函數內外的變量一起變化
傳值進去,函數內的變化不影響函數外
2.分析兩者:
2.1采用引用傳值的時候:
函數內部用&:
我們希望這個地址對應的變量會隨著變化 所以使用&? 一般是函數內部,因為函數內部就是要變量變化的嘛。
函數內對指定變量進行賦值(這里的賦值其實是地址對應的變量的賦值,所以用&)
與return返回值的時候使用&(這里返回也是返回&{變量}))
函數聲明的時候*:
因為是最終的結果? 所以直接用*? 不用再在乎是否變化? 一般是函數的入參與返回參數
2.2采用值傳遞的時候:
賦值用值傳遞 返回值的時候也用值傳遞? 過程中也用值傳遞就可以? 都沒有符號??
3.屬性加*的理解
一般屬性
因為int對應iptr,因為int是一個地址,所以iptr也是一地址;
我們傳入的參數就是以地址&i;
函數里面:*iptr=*&i=0 ?
我們對地址(iptr &i)進行賦值的,所以變量(*iptr i)都會發生變化;
這是從根上地址發生的變化;
所以我們對屬性加*的目的就很清楚了,
讓函數內外的變量一起變化。
屬性加*屬性的話? 調用的地方必定是&變量
集合屬性結構體
結構體加&與不加&進行賦值修改操作沒有任何影響。
package mainimport "fmt"type person struct {name stringage int }var a intfunc main() {// 一般展示// 結構體加&賦值 &{Ann 40}// 結構體不加賦值 {Ann 40}fmt.Println("結構體加&賦值",&person{name: "Ann", age: 40})fmt.Println("結構體不加賦值",person{name: "Ann", age: 40})// 加與不加獲取屬性值// 不加&進行獲取內部屬性值 50// 加&進行獲取內部屬性值 50a := person{name: "Sean", age: 50}b := &person{name: "Sean", age: 50}fmt.Println("不加&進行獲取內部屬性值",a.age)fmt.Println("加&進行獲取內部屬性值",b.age)// 加與不加修改屬性值// 不加&進行修改內部屬性值 51// 加&進行修改內部屬性值 51a.age = 51b.age = 51fmt.Println("不加&進行修改內部屬性值",a.age)fmt.Println("加&進行修改內部屬性值",b.age) }3.分析代碼
3.1底層使用了引用傳值,上層就會用引用傳值
3.2底層沒有用就不會使用引用傳值
3.3函數調用
4.實際代碼
package mainimport("fmt""reflect" )type b struct{c intd string }type bb struct{ff bdd string }type bbb struct{// 這句話是在表明// c是一個引用傳值// b對應地址c *bdd string }func main(){a:=1;// &{變量}=地址 給地址賦值哈 // *{地址}=值 取出地址值哈fmt.Println(&a); // 0xc042052058fmt.Println(*&a); // 1// fmt.Println(*a);//報錯 錯誤的指向 所以說a必須是一個地址 在這個例子中 a不是地址 所以報錯// 這個是結構體的簡單引用傳值與值傳遞// &{變量}-結構體的賦值先要聲明哪個類型結構體g:=&b{c:1,d:"gggg"};fmt.Println(g);// &{1 gggg}gg:=b{c:1,d:"gggg"};fmt.Println(gg);// {1 gggg}// 這個是結構體嵌套結構體進行值傳遞gggg:=bb{ff:b{c:1,d:"gggg"},dd:"gggg"}fmt.Println(gggg);// {{1 gggg} gggg}// 這個是結構體嵌套進行引用傳值 // 因為此時在bbb中b是一個地址&{}// c后面是結構體進行賦值 是對// 此處的b只是針對結構體b的 // *b 所以b為地址 所以傳遞地址即&bggggg:=bbb{c:&b{c:1,d:"gggg"},dd:"gggg"}fmt.Println(reflect.TypeOf(ggggg.c));//*main.bfmt.Println(ggggg.c); //&{1 gggg}fmt.Println(ggggg); // {0xc04204c420 gggg}// 這個是結構體嵌套進行引用傳值 // 這樣是錯誤的哈,在bbb里面b是引用傳值 直接用值傳遞會報錯// cannot use b literal (type b) as type *b in field value// 不能在字段值中使用b文字(類型b)作為類型*b// 就是說我們用的是b類型 在結構體聲明的時候是*b 所以錯誤// gggggg:=bbb{c:b{c:1,d:"gggg"},dd:"gggg"}// fmt.Println(gggggg); //錯誤// invalid indirect of b literal (type b) b字母無法指向b類)// ggggggg:=bbb{c:*b{c:1,d:"gggg"},dd:"gggg"}// fmt.Println(ggggggg); //錯誤// 結構體的定義要么是值傳遞(方式一) 要么是引用傳遞使用* 對類型定義(方式二)// 結構體的賦值要么是什么值傳遞(方式一) 要么引用傳遞-&類型名字{id:1,name:"aa"}(方式二)// 方式一對應方式一;方式二對應方式二 }// 0xc042052058 // 1 // &{1 gggg} // {1 gggg} // {{1 gggg} gggg} // *main.b // &{1 gggg} // {0xc04204c420 gggg}5.對應
// 結構體的定義要么是值傳遞(方式一) 要么是引用傳遞使用* 對類型定義(方式二)
// 結構體的賦值要么是什么值傳遞(方式一) 要么引用傳遞-&類型名字{id:1,name:"aa"}(方式二)
// 方式一對應方式一;方式二對應方式二
總結
- 上一篇: Go的结构体对接受者函数的传递
- 下一篇: 小霸王文化发展有限公司涉非法集资 怎么回