見出し画像

[Go言語 入門] ポインタ

golangで作ってみたいものがあり、golangを学び始めたので学習したことを書いていくノート。

---------------------------------------------------

サイトマップはこちら

---------------------------------------------------

第12回 ポインタ


変数はコンパイル時、メモリ上の「ある場所」に値が格納される。

この「ある場所」を示しているのがアドレスで、16進数で表される。

アドレスの確認は変数の前に「&」をつけることで確認可能。

// main.go

p := 100
fmt.Println(p, &p)

// 実行結果
// 100 0xc000012088

上記では「0xc000012088」がアドレスとなる。

では、変数にアドレスを格納するにはどのようにすればいいか。

アドレスの格納には以下のように「*」を付け、ポインタ型で定義する。

「var 変数名 *型名 = &アドレスを格納したい変数名」

p := 100
fmt.Println(p, &p)

var s *int = &p
fmt.Println(s)

// 実行結果
// 100 0xc000012088
// 0xc000012088

上記は、ポインタ型変数sに int 型変数pのアドレスを格納している例。

では、アドレスに格納されている値を表示するにはどのようにすればいいか。

変数の前に「*」をつける。

p := 100
var s *int = &p

fmt.Println(*s)
// 実行結果
// 100

変数sには変数pのアドレスが格納されている。

変数pは int 型の「100」を格納する変数。

上記のようにポインタ型変数の前に「*」をつけることで、アドレスに格納している値を参照することができる。


~ 渡す値による影響の違い ~

他の関数に、値を渡す場合とアドレスを渡す場合による違いは以下

// main2.go

// 値を渡すパターン
func calc(i int) {
	i = i * 10
}

// アドレスを渡すパターン
func calc_pointer(i *int) {
	*i *= 10
}

func main() {
	// 値を宣言
	i := 100
	calc(i)
	fmt.Println(i)

	calc_pointer(&i)
	fmt.Println(i)
}

// 実行結果
// 100
// 1000

別の関数に値を渡す場合は、値のみを渡しているため、calc関数を実行しても変数 i 自体には影響がない。

アドレスを渡した場合は、アドレスの中身を書き換えるため、上記の場合はアドレスの中身(100)を10倍する関数により、変数 i は「1000」となる。

【重要】アドレスを渡した場合、宣言した変数の値に影響がある!


~ 値が未確定のポインタを宣言するには ~

値は未確定だが、メモリのみ確保したい場合はnew()を使用する。

// main3.go

var p *int = new(int)
fmt.Println(p)
fmt.Println(*p)

// 実行結果
// 0xc00012c058 <-例
// 0

※new()で宣言したポインタの値は0で初期化される。

ちなみに、以下でも宣言自体は可能だが、アドレスは nil で初期化される。

var p *int
fmt.Println(p)
fmt.Println(*p)

// 実行結果
// <nil>
// エラー

こちらで宣言した場合、ポインタ型変数の初期値は nil となる。

ポインタ型変数pにアドレスが渡されるまではアドレスは nil であり、アドレス nil の値は参照することができないためエラーとなる。

【重要】アドレス nil の値は参照することができない!

以上


この記事が気に入ったらサポートをしてみませんか?