回答編集履歴

3

解説の修正

2022/09/06 05:54

投稿

nobonobo
nobonobo

スコア3367

test CHANGED
@@ -28,7 +28,7 @@
28
28
  ```
29
29
 
30
30
  型宣言だけだと、buckets==nilです。bucketsポインタの指す先に別のメモリがあてがわれて初めてmap型として機能します。
31
- key、elem、bucketポインタの指す先に別のメモリをあてる」のがmakeやリテラルなどを記述する方法です。
31
+ 「bucketsポインタの指す先に別のメモリをあてる」のがmakeやリテラルなどを記述する方法です。
32
32
  ```go
33
33
  m1 := map[string]int{}
34
34
  m2 := make(map[string]int)

2

mapの実体についての修正

2022/09/06 05:53

投稿

nobonobo
nobonobo

スコア3367

test CHANGED
@@ -8,23 +8,26 @@
8
8
 
9
9
  map型の内部表現
10
10
 
11
- https://github.com/golang/go/blob/c22a6c3b906cd37616d76da5f504c4c3e5677d94/src/runtime/type.go#L356-L367
11
+ https://github.com/golang/go/blob/2580d0e08d5e9f979b943758d3c49877fb2324cb/src/runtime/map.go#L116-L130
12
12
  ```go
13
- type maptype struct {
13
+ type hmap struct {
14
- typ _type
15
- key *_type
16
- elem *_type
17
- bucket *_type // internal type representing a hash bucket
14
+ // Note: the format of the hmap is also encoded in cmd/compile/internal/reflectdata/reflect.go.
18
- // function for hashing keys (ptr to key, seed) -> hash
15
+ // Make sure this stays in sync with the compiler's definition.
19
- hasher func(unsafe.Pointer, uintptr) uintptr
20
- keysize uint8 // size of key slot
16
+ count int // # live cells == size of map. Must be first (used by len() builtin)
21
- elemsize uint8 // size of elem slot
22
- bucketsize uint16 // size of bucket
23
- flags uint32
17
+ flags uint8
18
+ B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
19
+ noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
20
+ hash0 uint32 // hash seed
21
+
22
+ buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
23
+ oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
24
+ nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
25
+
26
+ extra *mapextra // optional fields
24
27
  }
25
28
  ```
26
29
 
27
- 型宣言で埋められるのはtypだけです。key、elem、bucketポインタの指す先に別のメモリがあてがわれて初めてmap型として機能します。
30
+ 型宣言だけだと、buckets==nilです。bucketsポインタの指す先に別のメモリがあてがわれて初めてmap型として機能します。
28
31
  「key、elem、bucketポインタの指す先に別のメモリをあてる」のがmakeやリテラルなどを記述する方法です。
29
32
  ```go
30
33
  m1 := map[string]int{}

1

まとめ追記

2022/09/04 15:11

投稿

nobonobo
nobonobo

スコア3367

test CHANGED
@@ -43,3 +43,6 @@
43
43
  }
44
44
  ```
45
45
  strポインタの指す先に文字列データが格納されている必要がありますが、こちらは「文字列値」そのものがコード中にあるのでそれをコンパイラはプログラムコードに埋め込み、そこへのポインタや長さが最初から算出可能なのでstrもlenもコンパイル時点で初期値を与えられます。
46
+
47
+ つまり、文字列もスライスもマップも宣言に関する情報を持つ構造体があり、実データは別途メモリ確保してそのポインタを構造体が持っているという形です。
48
+ 実データ用に別途初期化処理にてメモリ割り当てが必要です。それを行うのがmake関数やリテラル初期化による記述ということです。