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