マップタイプを関数に渡す

最近、 あるシンプルなタイプとスライスがメモリにどのように配置されるかについての記事が滑りました。 この記事から、「値によって」関数に渡されたスライスが、容量が増加したときに関数内のスライスがメモリ割り当てを必要とするまで参照によるスライスの転送である理由を学びました。 このスライスの容量関数内が変化し、ポインターとしてではなく「値で」渡された場合、スライスは呼び出し関数でさらに使用される配列ではなく、完全に異なる配列を参照し始めます。



プログラマがこれを考慮しなかった場合、スライスのこのような機能は、実行段階でプログラムのロジックに「ランダム」エラーを引き起こす可能性があります。



質問がありますが、 マップタイプには同様の状況がありますか? 結局、彼にはキャパシティもあり、値のペアの数を増やすことでメモリ内の割り当てを変更することもできます。



そして、私はこのようなコードを書くことで少し実験をしました:



package main import ( "fmt" ) type myMap map[string]string func main() { mymap := make(myMap, 1) mymap["firstKey"] = "firstValue" fmt.Printf("Init method nop: Address = %p Len = %d\n", &mymap, len(mymap)) mymap.grow() fmt.Printf("Growed method nop: Address = %p Len = %d\n", &mymap, len(mymap)) mymap = make(myMap, 1) mymap["firstKey"] = "firstValue" fmt.Printf("Init method p: Address = %p Len = %d\n", &mymap, len(mymap)) (&mymap).growp() fmt.Printf("Growed method p: Address = %p Len = %d\n", &mymap, len(mymap)) mymap = make(myMap, 1) mymap["firstKey"] = "firstValue" fmt.Printf("Init func nop: Address = %p Len = %d\n", &mymap, len(mymap)) fgrow(mymap) fmt.Printf("Growed func nop: Address = %p Len = %d\n", &mymap, len(mymap)) mymap = make(myMap, 1) mymap["firstKey"] = "firstValue" fmt.Printf("Init func p: Address = %p Len = %d\n", &mymap, len(mymap)) fgrowp(&mymap) fmt.Printf("Growed func p: Address = %p Len = %d\n", &mymap, len(mymap)) } func (m myMap) grow() { for i := 1; i < 1000000; i++ { m[fmt.Sprintf("nopAddKey%d", i)] = fmt.Sprintf("%d", i) } } func (m *myMap) growp() { for i := 1; i < 1000000; i++ { (*m)[fmt.Sprintf("pAddKey%d", i)] = fmt.Sprintf("%d", i) } } func fgrow(m myMap) { for i := 1; i < 1000000; i++ { m[fmt.Sprintf("nopAddKey%d", i)] = fmt.Sprintf("%d", i) } } func fgrowp(m *myMap) { for i := 1; i < 1000000; i++ { (*m)[fmt.Sprintf("pAddKey%d", i)] = fmt.Sprintf("%d", i) } }
      
      





ここでは、値とポインターによって、2つのメソッドと2つのマップ成長関数を定義しました。 実行の結果、次の結果が得られました。

初期化メソッドnop:アドレス= 0xc042054018 Len = 1

成長したメソッドnop:アドレス= 0xc042054018 Len = 1000000

初期化メソッドp:アドレス= 0xc042054018 Len = 1

成長したメソッドp:アドレス= 0xc042054018 Len = 1000000

Init func nop:アドレス= 0xc042054018 Len = 1

拡張されたfunc nop:アドレス= 0xc042054018 Len = 1000000

Init func p:アドレス= 0xc042054018 Len = 1

拡張された関数p:アドレス= 0xc042054018 Len = 1,000,000




したがって、呼び出し関数のマップは、値で渡された場合とポインターを通過した場合の両方で変化することがわかります。



All Articles