最近在使用Go的過程當中,遇到了和指針相關的一些問題,通過整理,發現和我最開始理解的指針還不太同樣。函數
問題一:在設計cache的時候,須要用到萬能類型interface來裝各類各樣的鍵值對,有時候有些參數根據須要得使用指針類型,剛開始會這樣寫測試
func test(a *interface{}){ //do something here ... }
會發現不管我傳什麼參數都會提示:this
cannot use *mytype as type *interface設計
這個問題與下面實際上是同一個問題。。。指針
問題二:有這麼一個需求,定義了一個接口A,在另外一個方法中,我想要設置一個參數是A的實現類型,由於這裏會涉及到數據的修改,所以確定是須要傳一個指針。所以,想固然的寫出了下面的代碼code
type myinterface interface{ print() } func test(value *myinterface){ //someting to do ... }
剛開始以爲沒有問題,可是!在調用test的時候遇到了問題。接口
type mystruct struct { i int } //實現接口 func (this *mystruct) print(){ fmt.Println(this.i) this.i=1 } func main(){ m := &mystruct{0} test(m)//錯誤 test(*m)//錯誤 }
*mystruct是實現了myinterface接口的,我但願test接收的是一個指針類型,所以傳*mystruct類型的數據。提示:Cannot use 'm' (type *mystruct) as type *myinterfaceit
說的很明確,沒法將*mystruct類型的數據賦值給*myinterface。經過查找各類資料,發如今go語言中,接口自己就是引用類型,換句話說,接口類型自己就是一個指針。對於個人需求,其實test的參數只要是myinterface就能夠了,只須要在傳值的時候,傳*mystruct類型(也只能傳*mystruct類型)class
使用下面的代碼測試一下test
//一個用於測試的接口 type myinterface interface{ print() } //*mystruct現了myinterface接口 type mystruct struct { i int } type mystruct2 struct { i int } /** 測試一下map類型的指針問題 */ func main() { //測試*mystruct實現效果 m := &mystruct{0} fmt.Printf("address in main is %p\n", m) method1(*m)//method1的參數是mystruct類型 m.print()//m的值並無受到影響 method2(m)//method2的參數是接口類型 m.print()//m的值被修改了 //測試mystruct2實現效果 fmt.Println("##########") m2 := &mystruct2{i:0} fmt.Printf("initial address is %p\n",m2) method3(*m2) m2.print() method2(m2) m2.print() } func method1(m mystruct) { fmt.Printf("address in method1 is %p\n", &m) m.print() } func method2(m myinterface){ fmt.Printf("address in method2 is %p\n",m) m.print() } func method3(m mystruct2){ fmt.Printf("address in method3 is %p\n",&m) m.print() } func (this *mystruct) print(){ fmt.Println(this.i) this.i=1 } func (this mystruct2) print(){ fmt.Println(this.i) this.i=2 }
運行結果以下:
address in main is 0xc42001c090 address in method1 is 0xc42001c098 0 0 address in method2 is 0xc42001c090 1 1 ########## initial address is 0xc42001c0b0 address in method3 is 0xc42001c0b8 0 0 address in method2 is 0xc42001c0b0 0 0
能夠看到,使用method2的時候,地址與main函數中的地址是同樣的,也就是說,當參數是myinterface的時候,傳的是一個引用類型。
另外,mystruct2不管使用哪一種方式都沒有改變main函數中的值,這個是由於mystruct2的print函數。
func (this mystruct2) print()
這種聲明實際上是
func print(this mystruct2)
能夠看出,在print函數中傳的是值,而非地址,所以不會影響到外部函數。
在這個過程當中看到過一位大神說的一句:永遠不要使用指向interface的指針,這個是沒有意義的