Go言語-ポインタ


ポインタ

プログラミング基本からGoの理解を文字におこして行こうと思います!

ポインタとは

アドレスは値
整数や文字列のように操作したり変数に代入することができる
Goではアドレスをポインタと呼んで扱っている
ポインタが代入された変数をポインタ型変数という

ポインタ型変数の定義

func main() {
  name := "tanabe"  //nameの値がstring型なので*string型になる

  var namePtr *string = &name
  fmt.Println(namePtr)

//コンソール
0xc421100230  //ポインタが出力

ポインタ型変数を定義するには
変数のデータ型に「*(アスタリスク)」をつけて宣言

ポインタ型変数namePtrを定義し、&nameで取得したポインタを代入している

ポインタからアクセスする

func main() {
  name := "tanabe"

  var namePtr *string = &name
  fmt.Println(*namePtr)  //namePtrが示す変数の値を出力
}

//コンソール
tanabe  //値が出力される

ポインタ型変数を定義するには
変数のデータ型に「*(アスタリスク)」をつけて宣言

ポインタを使って値を更新する

func main() {
  name := "tanabe"
  var namePtr *string = &name
  *namePtr = "naito"
  fmt.Println(name)  //namePtrが示す変数の値を出力
}

//コンソール
naito  //更新した値が出力される

ポインタ型変数を使用して、値を直接更新することもできる
更新するには「*変数名 = 更新する値」と記述

「*namePtr = "naito"」で、変数nameを更新

引数にポインタを指定する

func main() {
  name := "tanabe"
  changeName(&name)  //ポインタを引数に指定
}

func changeName(namePtr *string) {  //stringのポインタ型で受け取る
}

ポインタを別の関数に引数として指定する場合
受け取る関数には対応したポインタ型の引数を用意する必要がある

別の関数でポインタを使用し更新する

func main() {
  name := "tanabe"
  changeName(&name)  //ポインタを引数に指定
  fmt.Println(name)
}
func changeName(namePtr *string) {  //stringのポインタ型で受け取る
  *namePtr = "naito"
}

//コンソール
naito

ポインタを引数として指定することで
別の関数からでもポインタを使って元の変数を更新することができる

変数を引数に指定する

func main() {
  totalScore := 0
  fn(totalScore)
...
}
func fn(totalScore int) {
...
}

変数totalScoreを引数に指定する場合
その変数自体が渡されるわけではない

変数totalScoreの値がコピーされ、新しい変数に代入(値渡し)

渡した値を更新する

func main() {
  totalScore := 0
  fn(totalScore)
  fmt.Println(totalScore)  //totalScoreの値を出力
...
}
func fn(totalScore int) {
  totalScore += 10  //fn関数のtotalScoreのみ値を更新
}
//コンソール
0  //元の値が出力される

main関数とfn関数のそれぞれの変数totalScoreは、別の変数
そのため、fn関数のtotalScoreを更新しても
fn関数のtotalScoreのみ値が更新される

ポインタを見比べる

func main() {               func fn(totalScore int) {
  totalScore := 0             totalScore += 10
fn(totalScore)
fmt.Println(totalScore)     fmt.Println(totalScore)
  fmt.Println(&totalScore)     fmt.Println(&totalScore)
}                           }

//コンソール
fn関数のtotalScoreの値とポインタ
10  //元の値が出力される
0xc421100230

main関数のtotalScoreの値とポインタ
0
0xc421100052

main関数とfn関数のそれぞれのtotalScoreを出力すると
それらが実際に別の場所にある変数であることがわかる

引数のまとめ

引数に整数などの値を指定した場合

func main() {
  a := 10
  calculate(a)
  fmt.Println("引数に整数を指定した場合:", a)
}
func calculate(a int) {  //整数などの値を受け取る
  a += 1
}

//コンソール
引数に整数を指定した場合:10  //main関数の変数aはスコープが違うのでこのまま

calculate関数は受け取った引数に1を足す関数

変数aを引数に指定した場合、値がコピーされ別の変数が生成
よってcalculate関数で値を更新しても、main関数の変数aは更新されない

引数にポインタを指定した場合

func main() {
  b := 10
  calculate(&b)  //ポインタを渡す
  fmt.Println("引数にポインタを指定した場合:", b)
}
func calculate(bPtr*int)  //ポインタを貰う
  *bPtr
}
//コンソール
引数に整数を指定した場合:11  //main関数の変数bは値が更新される

ポインタを引数に指定すると、calculate関数から元の変数の値を更新できる
このとき、受け取る引数はポインタ型を指定することに注意