$emit传递多个参数_Go语言参数传递方式
一、函數參數傳遞方式
函數參數傳遞有2種方式:值傳遞和引用傳遞。
值傳遞是指調用函數時將參數值復制一份到函數,如果對函數參數進行修改,影響不到實際參數。
引用傳遞是指調用函數時將參數的指針傳遞到函數中,函數中對參數的修改,將影響到實際參數。
??不同編程語言的函數參數傳遞方式不盡相同,例如C語言中的int、float等參數類型采用值傳遞的方式,而數組類型默認為引用傳遞,C++中的引用傳遞顯而易見,其類型系統直接包含了引用類型。
二、Go語言中的函數傳遞方式
開門見山,直接上官方說法“Go語言函數傳遞方式都是值傳遞”。int64、string等類型采用值傳遞比較好理解,但是為什么說slice、interface、map和channel類型也是值傳遞呢?先看個例子1:
package main import "fmt" func fun0(slice0 []int) { slice0 = append(slice0, 2) fmt.Println("func0 : ", slice0)} func main() { slice0 := []int{1} fun0(slice0) fmt.Println("main : ", slice0)}打印結果:
func0 : [1 2]main : [1]分析:fun0中slice0追加元素并沒有影響到main函數中的slice0,可見slice采用的是值傳遞方式。
我們再看另外一個例子2:
package main import "fmt" func fun0(map0 map[string]int) { map0["fun0"] = 1 fmt.Println("func0 : ", map0)} func main() { map0 := map[string]int{"main":1} fun0(map0) fmt.Println("main : ", map0)}打印結果:
func0 : map[fun0:1 main:1]main : map[fun0:1 main:1]分析:func0中map0添加新元素,但是確實是影響到了main函數中的map0,看著好像map采用的是引用傳遞方式,實則不然。
三、為什么說map、slice等類型采用值傳遞?
看似slice類型為值傳遞,map類型為引用傳遞,而實際上卻都是值傳遞。為什么會出現上述兩種不同的情況呢?為了方便說明這種現象,本文根據slice、map、interface和channel等類型的實現做一些抽象,將這些類型統一表示為1個結構體,其中包含一個或多個指針,指向數據真正的存儲,如下圖所示。
有了上述抽象,我們再看下,當slice、map、interface和channel變量作為參數傳遞到另外一個函數時,會出現什么樣的情況。以第二節中的2個例子來說明,入參和形參的存儲結構如下圖所示。
?
可以看出,參數傳遞前后data數據并沒有發生變化,但struct結構卻是不同的,被調函數中生成了一份struct副本。
3.1 slice的函數傳遞方式
在例子1中func0中調用append追加了1個元素,有2種可能的情況:1、數組容量不足,append導致數組擴展;2、數組容量充足,append只是在原來的data存儲增加了1個元素。兩者分別對應的存儲如下圖所示。
第一種情況,struct和data都和原來的入參分道揚鑣,fun0中的修改當然不會什么影響到main函數。
第二種情況,slice在參數傳遞前后共用一段存儲data,但是需要注意的是struct結構中的len前后不同,因此main函數中同樣不能感知到有新追加的元素。
這就解釋了為什么fun0中slice追加新元素,在main函數中無影響。
3.2 Map中的函數傳遞方式
在例子2中,func0調用map0[“fun0”]=2,調用前后的存儲結構,如下圖所示。
可以看出fun0中追加元素同樣在main中也能感知到。那能否據此說,Go語言中的map采用的是引用傳遞的方式呢?其實是不對的,看個例子3:
package main import "fmt" func fun0(map0 map[string]int) { map0 = map[string]int { "fun0":1, } fmt.Println("func0 : ", map0)} func main() { map0 := map[string]int{"main":1} fun0(map0) fmt.Println("main : ", map0)}打印結果:
func0 : map[fun0:1]main : map[main:1]分析:func0中重新賦值map0,并沒有影響到main函數,所以map的傳遞其實也是值傳遞,從調用前后的存儲結構圖,也可以一窺究竟。
??那有沒有什么辦法不通過返回值重新賦值,使得被調函數的參數改變能夠影響到主調函數呢?當然是有辦法的,就是直接傳遞變量的指針例如代碼4。不過Go語言并不建議采用這樣方式來實現引用傳遞。
package main import "fmt" func fun0(map0 *map[string]int) { *map0 = map[string]int { "fun0":1, } fmt.Println("func0 : ", *map0)} func main() {????map0?:=?map[string]int{"main":1}????fun0(&map0) fmt.Println("main?:?",?map0)}打印結果:
func0 : map[fun0:1]main : map[fun0:1]總結
以上是生活随笔為你收集整理的$emit传递多个参数_Go语言参数传递方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: div超出不换行_一日一技:XPath不
- 下一篇: c++宏定义常量为什么使用移位_干货 |