どうも, @nomurakkoooです.
今回はGoを触っていてポインタについて少し調べたので書きます.
初心者レベルです. よろしくどうぞ
ポインタとは
GoとかCとかでよく見る*
とか&
.
変数のアドレスを参照して値を取得したり, 更新したりするやつという認識です.
間違えていたら優しく教えてください.
*
と&
ってなに
簡単にいうと*
は変数に対するアドレスの中身の参照で&
は変数のアドレスヘのアクセスです.
&
の方はしっくり来る例えがパッと思い浮かびませんでした.
こんなのあるよとかこっちの方が良くない?とかあったら是非教えてください.
簡単な例を挙げると
1: package main
2:
3: import "fmt"
4:
5: func main() {
6: var pointer *string
7: var name string = "nomurakkooo"
8:
9: pointer = &name
10:
11: fmt.Println("&name: ", &name)
12: fmt.Println("pointer: ", pointer)
13: fmt.Println("name: ", name)
14: fmt.Println("*pointer: ", *pointer)
15: }
&name: 0xc42007e050
pointer: 0xc42007e050
name: nomurakkooo
*pointer: nomurakkooo
なぜ使うのか
関数に引数を渡す時, それは全てコピーを渡している.
関数内で引数として渡された値を更新したいときや引数が大きすぎてコピーしたくないなーってときに使おう.
ちなみに, コピーを渡すということは変数を参照するアドレスは変化している.
変化しているからこそ参照元の値が更新されないというわけですね.
関数へのポインタ渡しについて
前記の「なぜ使うのか」 というところにもつながる.
引数をポインタで渡すことにより参照元のアドレス, 値の共有を行う.
簡単に渡してみる
1: package main
2:
3: import "fmt"
4:
5: type Nomurakkooo struct {
6: first string
7: last string
8: }
9:
10: func updateName(name *Nomurakkooo) {
11: name.first = "nomurakkooo"
12: name.last = "rakko"
13:
14: fmt.Println("関数内:", name.first, name.last)
15: }
16:
17: func main() {
18: fullName := Nomurakkooo{first: "nomura", last: "kouta"}
19:
20: fmt.Println("更新前:", fullName)
21:
22: updateName(&fullName)
23:
24: fmt.Println("更新後:", fullName)
25: }
更新前: {nomura kouta}
関数内: nomurakkooo rakko
更新後: {nomurakkooo rakko}
構造体の場合は11, 12行目で(*name).first
とかじゃなくてええんかって思うのですがname.first
でも指定できるみたいです.
アドレスへの参照の仕方は*
をつけるで統一したほうが良い感は伝わって来るが実際どうなのでしょう.
わかる方いらっしゃいましたら教授いただけると幸いです.
まとめ
間違えて覚えてしまいそうなところなので気をつけよう!