はじめに
最近業務でgo言語を触り始めそうな予感がしている今日この頃です。
それまでrubyやjavaしか触ってきておらず、ポインタを意識せずに人生を送ってきました。
なんとなくポインタに付いては理解できているのですが、*
や&
の使い分けが混乱しそうなので備忘録として書き留めておきます。
アンパサンド(&)は変数toポインタを行う
アンパサンドは、変数からそのポインタを抽出するのに使用します。
ポインタなので出力結果に&
が付いていることがわかります。
type Hoge struct {
x, y int
}
func main() {
v := Hoge{1,2}
p := &v
fmt.Println(p)
pp := &Hoge{3,4}
fmt.Println(pp)
}
出力結果
&{1 2}
&{3 4}
アスタリスク(*)はポインタto変数を行う
アスタリスクはポインタが指し示す変数の実体を抽出します。
func main() {
p := &Hoge{1,2}
v := *p
fmt.Println(v)
}
出力結果
{1 2}
アスタリスク(*)はポインタ型の宣言をするときに使用する
&と役割が似ていて紛らわしいのですが、
&は既に宣言されている変数のポインタを抽出するのに対し、
*はポインタ型を示します。
func main() {
p := &Hoge{1,2}
// ↑は var p *Hoge = &Hoge{1,2} を行っている
v := Hoge{1,2}
pp := &v
fmt.Println(p, pp)
}
出力結果
&{1 2} &{1 2}
なので、メソッドの引数に*
が付与されている場合は、ポインタ型の変数を引数として受け取るということを示しています。
func change_func(h *Hoge) {
h.x = 3
h.y = 3
}
func main() {
v := Hoge{1,2}
change_func(&v)
fmt.Println(v)
}
出力結果
{3 3}
ポインタを引数に渡す関数での使用例
func change_func(i *int) {
*i = 10
}
func main() {
i := 1
change_func(&i)
fmt.Println(i)
}
出力結果
10
↑の例ではint型のポインタをメソッドに渡し、
メソッド内で変数に変換し、値を代入することで、呼び出し元の変数の値も変更しています。
func change_func(v *Hoge) {
v.x = 3
v.y = 4
}
func main() {
v := Hoge{1,2}
change_func(&v)
fmt.Println(v)
}
出力結果
{3,4}
↑の例ではHoge型のポインタをメソッドに渡し、呼び出し元の変数の値も変更しています。
structはメソッド側で*
を付与しなくても、直接各フィールドに値を代入できます。