0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Go入門】Golang基礎入門+αの備忘録#3(ポインタ)

Last updated at Posted at 2025-03-03

はじめに

【Go入門】Golang基礎入門+αの備忘録#2の続き。
この記事は以下のUdemyコースの学習記録です。

重要だと思った部分や感想、復習用に何を学んだかを書いていきます。

セクション10:ポインタ

ポインタ

ポインタの基本を学んだ。

簡単にまとめる

Goの値型と参照型とポインタ型についてまとめる。

  • 値型
    値型は代入する度に新しいメモリ領域(スタック上のメモリ領域)が確保される。(int,float,bool,stringなど。ただし、stringは内部的には参照型なような挙動をする)。
    関数に渡すと新たな変数としてコピーされ、その関数内のローカル変数となる。このローカル変数のデータをどれだけ変えても関数外の元の変数は変更されない。
  • 参照型
    各参照型は構造体として定義されており、構造体内にはポインタが含まれているため、ポインタ型のような動作をする。
  • ポインタ型
    メモリアドレスのみ直接もたせることができる。

ポインタ型のような動作とは?

参照型はGoの内部実装でポインタを含む構造体になっている。そのため、参照型を宣言するとその参照型の内部(構造体)の設計によって同時にヒープ上のメモリアドレスも確保されるため、ポインタのような動作をする(ポインタ+メタデータ(例:slice→ポインタ、len、cap)を値渡しし、それによってポインタのように動作する)。

本題

ポインタ型

  • ポインタ型とはアドレス(メモリ上の特定の場所(どこを指しているのか)を示す情報)情報のみを格納する型。
  • ポインタとはアドレスという情報を持つデータ。
  • 基本的にデータは宣言するとメモリ上のどこかに割り当てられるため、データ毎に固有のメモリアドレスが存在する。このメモリアドレスを取得し、ポインタ型に代入することでデータを関節的に参照、操作することができる。
  • 型の前に*をつけてポインタ型を表す。&nとすることで変数nのメモリアドレスを取得する。
    ポインタ型pに変数nのメモリアドレスを代入する。(基本型のpにメモリアドレスを代入すると型の不一致でコンパイルエラーになる)。
p *int = &n

ポインタが指す値を取得する(デリファレンス)

*p

ポインタ型の変数に、異なる関数間で共有したいデータのメモリアドレスを代入することで、異なる関数間で同じメモリ領域のデータを共有できる。

func updateValue(pointer *int) {
	*pointer = 100 // ポインタを使って値を変更
}

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

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

主要な参照型整理

各参照型の構造体の各フィールドにコメントで説明追加(ChatGPTで日本語訳+追加)
slice
sliceの実態。

type slice struct {
	array unsafe.Pointer // ポインタ
	len   int // 長さ
	cap   int // 容量
}

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

map
mapの実態。

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 // オプションの追加フィールド (マップの種類によって異なる)
}

hmapのhはハッシュを意味するそう。mapはデータ構造がハッシュテーブルで、が〇〇でこういう名前になっているらしい。
参考
【Go】Mapの内部構造とO(1)のメカニズム)
Go言語: ポインターとそれに関する型(uintptr, unsafe.Pointer)

channel
channelの実態。

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
}

interface
interfaceの実態

type iface struct {
	tab  *itab         // 型情報 (メソッドテーブル)
	data unsafe.Pointer // 実際のデータへのポインタ
}

func
funcの実態。

type funcval struct {
	fn uintptr // 関数の実行コードへのポインタ

	// ここから先は可変サイズのデータ領域
	// クロージャの場合、キャプチャされた変数がここに格納される
}


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

参考

データ型について動作確認(基本型・合成型・参照型・型変換[キャスト])
Golang_ポインタ型と参照型 #460
もう怖くない!Goのポインタを理解しよう!

0
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?