LoginSignup
150
87

More than 5 years have passed since last update.

Go言語におけるポインタのアンパサンド(&)とアスタリスク(*)の違い

Last updated at Posted at 2018-04-14

はじめに

最近業務で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はメソッド側で*を付与しなくても、直接各フィールドに値を代入できます。

150
87
0

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
150
87