激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Golang - Go 值傳遞與引用傳遞的方法

Go 值傳遞與引用傳遞的方法

2020-05-23 11:59chencanxin Golang

這篇文章主要介紹了Go 值傳遞與引用傳遞的方法,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

問題引入

  • 什么時候選擇 T 作為參數類型,什么時候選擇 *T 作為參數類型?
  • [ ] T 是傳遞的指針還是值?選擇 [ ] T 還是 [ ] *T ?
  • 哪些類型復制和傳遞的時候會創建副本?
  • 什么情況下會發生副本創建?

T 和 *T 當做函數參數時都是傳遞它的副本

先看傳 T 的情況:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
type user struct {
  id int
  name string
}
 
func passByValue(_u user){
  _u.id++
  _u.name="jack"
 
  // when printing structs, the plus flag (%+v) adds field names
  fmt.Printf("_u 值:%+v;地址:%p; \n",_u,&_u)
}
 
func exp2(){
  u:=user{1,"peter"}
  fmt.Printf("原始 u 值:%+v; 地址: %p;\n",u,&u)
  passByValue(u)
  fmt.Printf("執行完函數后 u 值:%+v; 地址: %p;\n",u,&u)
}

執行 exp2 方法,輸出結果為:

Go 值傳遞與引用傳遞的方法

結果說明:

  • _u 是 u 的一份拷貝,地址不同
  • 函數內對參數的改變不影響原始的對象

再看傳 *T 的情況:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type user struct {
  id int
  name string
}
 
func passByPointer(_u *user){
  _u.id++
  _u.name="jack"
  fmt.Printf("_u 值:%+v ;u指向的地址:%p; u本身存放地址:%p; \n",*_u,_u,&_u)
}
 
func exp3(){
  u:=&user{1,"peter"}
  fmt.Printf("原始u 值:%+v; 指向的地址: %p;u本身存放地址: %p; \n",*u,u,&u)
  passByPointer(u)
  fmt.Printf("原始u 值:%+v; 指向的地址: %p;u本身存放地址: %p; \n",*u,u,&u)
}

執行 exp3 方法的輸出結果為:

Go 值傳遞與引用傳遞的方法

注意到,雖然參數 _u 仍然是 u 的一份拷貝對象,但是原始對象的值還是改變了。可以這么理解,因為 u 指針和 _u 指針都指向同一個對象,即 0xc0000484a0 地址上存放的對象,_u.name="jack"可以看做*(_u).name="jack,即取值后再改變值。

改變指針參數的地址

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type user struct {
  id int
  name string
}
 
func changeAddress(_u *user){
  _u=&user{2,"jack"}
  fmt.Printf("參數_u 值:%+v ;u指向的地址:%p; u本身存放地址:%p; \n",*_u,_u,&_u)
  return
}
 
func exp4(){
  u:=&user{1,"peter"}
  fmt.Printf("原始u 值:%+v; 指向的地址: %p;u本身存放地址: %p; \n",*u,u,&u)
  changeAddress(u)
  fmt.Printf("執行函數后 u 值:%+v; 指向的地址: %p;u本身存放地址: %p; \n",*u,u,&u)
}

輸出結果如下:

Go 值傳遞與引用傳遞的方法

注意,執行函數后 u 值沒有改變!改變了參數指向的地址,原來的對象肯定就不受影響了。

傳遞數組參數 vs 傳遞切片參數

?
1
2
3
4
5
6
7
8
9
10
11
func passSlice(_s []int){
  _s[0]=99
  fmt.Printf("_s 值:%v,地址:%p\n",_s,&_s)
}
 
func exp6(){
  s:=[]int{11,22,33,44}
  fmt.Printf("s 值:%v,地址:%p\n",s,&s)
  passSlice(s)
  fmt.Printf("執行函數后 s 值:%v,地址:%p\n",s,&s)
}

Go 值傳遞與引用傳遞的方法

對切片參數的修改會影響原來的切片。

再看傳遞數組

?
1
2
3
4
5
6
7
8
9
10
11
func passArray(_a [3]int){
  _a[0]=99
  fmt.Printf("_a 值:%v,地址:%p\n",_a,&_a)
}
 
func exp7(){
  a:=[3]int{22,33,44}
  fmt.Printf("a 值:%v,地址:%p\n",a,&a)
  passArray(a)
  fmt.Printf("執行函數后 a 值:%v,地址:%p\n",a,&a)
}

Go 值傳遞與引用傳遞的方法

對數組參數的修改并不會影響原來的切片。

總結會發生副本創建的情況

  • 賦值操作,如 u1:=u2。包括 slice,map,array 在初始化和按索引設置的時候都會創建副本
  • for-range循環也是將元素的副本賦值給循環變量,但注意一點,循環變量是被復用的,所以地址不會變
  • 將變量作為參數傳遞。但注意一點, slice,map,chanel 三者都和 *T 一樣,屬于引用傳遞,雖然是發生了副本創建,但是函數內對參數的值進行修改會影響原來的值。而數組不同于 slice,函數內對數組參數的值進行修改不會影響原來數組
  • 將返回值賦值給其它變量或者傳遞給其它的函數和方法
  • 字符串比較特殊,它的值不能修改,任何想對字符串的值做修改都會生成新的字符串
  • 函數也是一個指針類型,對函數對象的賦值只是又創建了一個對次函數對象的指針。

總結指針類型

  • slice
  • map
  • chanel
  • 函數

如何選擇 T 和 *T

對函數的參數或者返回值定義成 T 還是 *T 要考慮以下幾點:

  • 一般的判斷標準是看副本創建的成本和需求。
  • 如果不想變量被函數所修改,那么選擇類型 T
  • 如果變量是一個很大的struct或者數組,副本的創建相對會影響性能,這個時候要考慮使用*T,只創建新的指針
  • 對于函數作用域內的參數,如果定義成 T , Go 編譯器盡量將對象分配到棧上,而 *T 很可能會分配到對象上,這對垃圾回收會有影響

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://segmentfault.com/a/1190000018538664

 

延伸 · 閱讀

精彩推薦
  • Golanggo日志系統logrus顯示文件和行號的操作

    go日志系統logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統logrus顯示文件和行號的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
  • Golanggolang的httpserver優雅重啟方法詳解

    golang的httpserver優雅重啟方法詳解

    這篇文章主要給大家介紹了關于golang的httpserver優雅重啟的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    helight2992020-05-14
  • GolangGolang通脈之數據類型詳情

    Golang通脈之數據類型詳情

    這篇文章主要介紹了Golang通脈之數據類型,在編程語言中標識符就是定義的具有某種意義的詞,比如變量名、常量名、函數名等等,Go語言中標識符允許由...

    4272021-11-24
  • GolangGolang中Bit數組的實現方式

    Golang中Bit數組的實現方式

    這篇文章主要介紹了Golang中Bit數組的實現方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨尊11682021-06-09
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • Golanggolang如何使用struct的tag屬性的詳細介紹

    golang如何使用struct的tag屬性的詳細介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細介紹,從例子說起,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看...

    Go語言中文網11352020-05-21
  • Golanggolang json.Marshal 特殊html字符被轉義的解決方法

    golang json.Marshal 特殊html字符被轉義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉義的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 一区二区久久久久草草 | 在线亚洲欧美 | 色吧久久 | 亚洲午夜精品视频 | 成人精品久久久 | 一级一片免费看 | 国产99久久精品 | 亚洲午夜在线视频 | 99影视在线视频免费观看 | 狠狠久久 | 精品一区二区三区网站 | 久久综合婷婷 | 色网免费观看 | 亚洲成人第一区 | 色视频91| 99ri在线| 精品国产91一区二区三区 | 午夜激情视频免费 | 精品国产欧美一区二区 | 国产女厕一区二区三区在线视 | 高潮激情aaaaa免费看 | 亚洲国产超高清a毛毛片 | 欧美成人免费小视频 | 国产毛片自拍 | 91久久精品一二三区 | av成人免费看 | 日韩视频―中文字幕 | 亚洲3p激情在线观看 | 麻豆视频在线观看免费网站 | 久久久国产一级片 | 91色爱| 欧美a级大胆视频 | 国产成人精品网站 | 羞羞视频免费网站男男 | 欧美一级黄色网 | 在线成人免费观看视频 | 亚洲精品av在线 | 91福利影视 | 露脸各种姿势啪啪的清纯美女 | 极品xxxx欧美一区二区 | 亚洲精品久久久久久 |