Go言語のポインタについて
アドレスとは
アドレスとは、変数の内容が保存されるメモリの場所を示す16進数の値である。変数名の前に&
をつけることでアドレスを提供する.このように定義された変数をポインタ変数という
a := "aaaa"
b := &a // bはポインタ変数になる
ポインタとは
仕組みとしてはアドレスが格納されているポインタ変数に対して、*をつけることで、アドレスの中身にアクセスすることができる。ポインタとは、格納されている値の型情報とアドレスから成り立っている.
a := "aaaa"
b := &a // bはポインタ変数になる
fmt.Println(*b) // これでaaaaと出力される。
ポインタのメリット
ポインタを利用することで参照渡しが実現できる。参照渡しとは、アドレスを渡すことで変数自体を渡すことである。参照私に対する言葉として値渡しがあるが、値渡しとは、変数の中身をコピーして関数にわたしていることになる。 C言語などと異なり、ポインタに対しての加算はできないので気をつけること。
package main
import "fmt"
func incrementPassByValue(i int) {
i = i + 1
fmt.Println(i)
}
func incrementPassByReference(i *int) {
i = i + 1 //ポインタの加算はできないので注意すること
fmt.Println(i)
}
func main() {
i := 100
fmt.Println(i) // 100
incrementPassByValue(i) // 101
fmt.Println(i) // 100
incrementPassByReference(&i) // 101、、と行きたいところだがコンパイルできない。
fmt.Println(i) // 101
}
ポインタレシーバとは
ではポインタとして変数を変えたいときはどうするべきか。これはポインタレシーバを利用するのが良いと思う
package main
import "fmt"
type Person struct {
Age int
Name string
}
func (p Person) increment() {
p.Age = p.Age + 1
}
func (p *Person) incrementByReference() {
p.Age = p.Age + 1
}
func main() {
person := &Person{Age: 24, Name: "田中太郎"}
person.increment()
fmt.Println(person.Age) // 24のまま
person.incrementByReference()
fmt.Println(person.Age) // 25になる
}
まとめ
中のメソッドを更新するときはPointerレシーバーを使おう。