【1日目】Go言語の学習

変数のスコープ

main関数の中で宣言した score変数は、main関数内でのみ使用できる。変数が使える範囲をスコープと呼ぶ。

package main

func main() {
    score := 1
    // スコープ内なので使える
    println(score)
}

func sub() {
    // スコープ外なので使えない
    score += 1
}

■ 実行結果

# command-line-arguments
./Main.go:12:5: undefined: score

値のコピー

score変数を main関数から sub関数に渡し、値を更新しているように見えるが、main関数側では score変数の値は変わらない。

package main

func main() {
    score := 1
    sub(score)
    println(score) //=>1
}

func sub(score int) {
    score += 1
    println(score) //=>2
}

■ 実行結果

2
1


実際には、sub関数にはコピーされた変数が渡されているだけで、main関数の変数とは別のもの。変数のアドレス (Goではポインタ)を出力してみると、値が違うことがわかる。

package main

func main() {
    score := 1
    sub(score)
    println(&score) //=>0xc00002c748
}

func sub(score int) {
    score += 1
    println(&score) //=>0xc00002c740
}

■ 実行結果

0xc00002c740
0xc00002c748

ポインタ渡し

sub関数で socre変数の値を更新するには、ポインタを渡せば良い。

package main

func main() {
    score := 1
    sub(&score)
    println(score) //=>2
}

func sub(score *int) {
    *score += 1
}

■ 実行結果

2


main関数から sub関数に対してポインタを渡す。

sub(&score)


sub関数では、①ポインタ変数を定義してポインタを受け取り、②ポインタを使って値を更新。

func sub(score *int) { -①
    *score += 1 -②
}

補足

関数の引数における値とポインタの使い分けについて、公式ドキュメントの Should I define methods on values or pointers? によると、

  • ここまででも述べたように、引数を更新する場合は「ポインタ」
  • 引数のサイズが大きい場合は「ポインタ」
  • 逆に、引数のサイズが小さいのであれば「値」