【Go入門】Golang基礎入門＋αの備忘録#3（ポインタ）

# はじめに
[【Go入門】Golang基礎入門＋αの備忘録#2](https://qiita.com/sabotenten/items/21ddd93713aba447d697/ "")の続き。
この記事は以下のUdemyコースの学習記録です。

https://www.udemy.com/course/golang-webgosql/?couponCode=KEEPLEARNING

重要だと思った部分や感想、復習用に何を学んだかを書いていきます。
## セクション10：ポインタ
### ポインタ
ポインタの基本を学んだ。
#### 簡単にまとめる
Goの値型と参照型とポインタ型についてまとめる。
- 値型
値型は代入する度に新しいメモリ領域（スタック上のメモリ領域）が確保される。（int,float,bool,stringなど。ただし、stringは内部的には参照型なような挙動をする）。
関数に渡すと新たな変数としてコピーされ、その関数内のローカル変数となる。このローカル変数のデータをどれだけ変えても関数外の元の変数は変更されない。
- 参照型
各参照型は構造体として定義されており、構造体内にはポインタが含まれているため、ポインタ型のような動作をする。
- ポインタ型
メモリアドレスのみ直接もたせることができる。
#### ポインタ型のような動作とは？
参照型はGoの内部実装で`ポインタを含む構造体`になっている。そのため、参照型を宣言するとその参照型の内部（構造体）の設計によって同時にヒープ上のメモリアドレスも確保されるため、ポインタのような動作をする（ポインタ＋メタデータ（例：slice→ポインタ、len、cap）を値渡しし、それによってポインタのように動作する）。
#### 本題
ポインタ型
- ポインタ型とはアドレス（メモリ上の特定の場所（どこを指しているのか）を示す情報）情報のみを格納する型。
- ポインタとはアドレスという情報を持つデータ。
- 基本的にデータは宣言するとメモリ上のどこかに割り当てられるため、データ毎に固有のメモリアドレスが存在する。このメモリアドレスを取得し、ポインタ型に代入することでデータを関節的に参照、操作することができる。
- 型の前に`*`をつけてポインタ型を表す。`&n`とすることで変数nのメモリアドレスを取得する。
ポインタ型pに変数nのメモリアドレスを代入する。（基本型のpにメモリアドレスを代入すると型の不一致でコンパイルエラーになる）。
```go:
p *int = &n
```
ポインタが指す値を取得する（デリファレンス）
```go:
*p
```

ポインタ型の変数に、異なる関数間で共有したいデータのメモリアドレスを代入することで、異なる関数間で同じメモリ領域のデータを共有できる。
```go:
func updateValue(pointer *int) {
	*pointer = 100 // ポインタを使って値を変更
}

func main() {
	num := 10
	fmt.Println(num) // 出力結果：10

	updateValue(&num) // numのアドレスを取得したポインタを渡す
	fmt.Println(num) // 出力結果：100
}
```

#### 主要な参照型整理
各参照型の構造体の各フィールドにコメントで説明追加（ChatGPTで日本語訳+追加）
**slice**
sliceの実態。
```go:
type slice struct {
	array unsafe.Pointer // ポインタ
	len   int // 長さ
	cap   int // 容量
}
```
https://github.com/golang/go/blob/master/src/runtime/slice.go

- スライスを宣言すると、内部的にはスライス構造体（slice）が生成される。このスライス構造体にはポインタが含まれているため、スライスのコピーが行われると、スライス構造体に含まれるポインタもコピーされるため、スライスはポインタのような動作をする。
- 

**map**
mapの実態。
```go:
type hmap struct {
	// count: マップ内の有効なキーと値のペアの数
	//       ※ len(map) の計算に使われるため、最初のフィールドである必要がある
	count int 
	flags     uint8  // マップの状態を示すフラグ
	B         uint8  // バケット数の指数 (2^B 個のバケットを持つ)
	noverflow uint16 // 溢れたバケットの数（概算値）
	hash0     uint32 // ハッシュ計算のためのシード値 (ランダムな値)

	buckets    unsafe.Pointer // 2^B 個のバケットを格納する配列へのポインタ (マップが空なら nil)
	oldbuckets unsafe.Pointer // マップのリサイズ時に使われる、古いバケット配列へのポインタ (通常は nil)
	nevacuate  uintptr        // リサイズの進行状況を示すカウンタ (この値より小さいバケットは移行済み)
	clearSeq   uint64         // クリア処理のためのシーケンス番号

	extra *mapextra // オプションの追加フィールド (マップの種類によって異なる)
}

```
https://github.com/golang/go/blob/b199d9766a8957c686ece568483586f08fc9a8b4/src/runtime/map_noswiss.go#L112

hmapのhはハッシュを意味するそう。mapはデータ構造がハッシュテーブルで、が〇〇でこういう名前になっているらしい。
**参考**
[【Go】Mapの内部構造とO(1)のメカニズム)](https://zenn.dev/smartshopping/articles/5df9c3717e25bd/ "")
[Go言語: ポインターとそれに関する型(uintptr, unsafe.Pointer)](https://qiita.com/nozmiz/items/291f16f619a939bd7b87/ "")

**channel**
channelの実態。
```go:
type hchan struct {
	qcount   uint           // 現在のキュー内の要素数
	dataqsiz uint           // キューのサイズ（バッファサイズ、0なら非バッファチャネル）
	buf      unsafe.Pointer // dataqsiz 要素分の配列を指すポインタ（バッファ）
	elemsize uint16         // 要素のサイズ（バイト単位）
	synctest bool           // true の場合、同期テスト用のバブル内で作成されたことを示す
	closed   uint32         // チャネルが閉じられているかどうか (0: 開いている, 1: 閉じている)
	timer    *timer         // チャネルに関連するタイマー（タイムアウトなどに使用）
	elemtype *_type         // チャネルで扱う要素の型情報
	sendx    uint           // 送信時のインデックス（バッファのリングバッファ用）
	recvx    uint           // 受信時のインデックス（バッファのリングバッファ用）
	recvq    waitq          // 受信待ちのゴルーチンリスト（ブロックしている受信側）
	sendq    waitq          // 送信待ちのゴルーチンリスト（ブロックしている送信側）

	// 🔒 lock: hchan の全フィールドと、チャネルでブロックされている goroutine の一部の状態を保護するミューテックス
	//
	// ⚠️ lock を保持したまま別の goroutine の状態を変更しないこと！
	//  (特に、別の goroutine をレディ状態にしないこと)。
	//  これは、スタックの縮小とデッドロックを引き起こす可能性があるため。
	lock mutex
}
```
https://github.com/golang/go/blob/b199d9766a8957c686ece568483586f08fc9a8b4/src/runtime/chan.go#L33

**interface**
interfaceの実態
```go:
type iface struct {
	tab  *itab         // 型情報 (メソッドテーブル)
	data unsafe.Pointer // 実際のデータへのポインタ
}
```
https://github.com/golang/go/blob/b199d9766a8957c686ece568483586f08fc9a8b4/src/runtime/runtime2.go#L179

**func**
funcの実態。
```go:
type funcval struct {
	fn uintptr // 関数の実行コードへのポインタ

	// ここから先は可変サイズのデータ領域
	// クロージャの場合、キャプチャされた変数がここに格納される
}
```
https://github.com/golang/go/blob/b199d9766a8957c686ece568483586f08fc9a8b4/src/runtime/runtime2.go#L175

---
一旦フィールドに何があるかだけ理解。

#### 参考
[データ型について動作確認(基本型・合成型・参照型・型変換[キャスト])](https://www.wakuwakubank.com/posts/776-go-datatype/#index_id11/ "")
[Golang_ポインタ型と参照型　#460](https://note.com/ym202110/n/n0f046445f319/ "")
[もう怖くない！Goのポインタを理解しよう！](https://qiita.com/hiroaki-u/items/da7694ecffccbb49a139/ "")