今までRoRやPHPなどの動的型付言語をメインでやってきたんですが、今回行っているインターン先で、Go
を使うことになったので、勉強しています。
そのなかで、初めて知った概念であるポインタについて今回は解説していこうと思います。
今回の記事を読んでわかることは以下の3つです。
- ポインタとはなんなのか
- ポインタの書き方
- ポインタってなぜ必要なのか
この2つがわかるようになると思いますので、最後までお付き合いお願いいたします。
なお、この記事では公式のPlayGroundからハンズオンでコピペではなく、手を動かしてみるのをお勧めします
ポインタとは何なのか?
簡潔に言えば、ポインタとはアドレス情報であるメモリにアクセスするためのものです。
メモリとは一時的にデータが保存されている場所でその中に変数が保存されています。
メモリについてはこちらの記事が参考になるのでぜひ。
例として以下のコードを見てください
package main
import "fmt"
type Fruit struct {
Id int
Name string
}
func main() {
var f *Fruit
f = &Fruit{
Id: 1,
Name: "ばなな",
}
fmt.Printf("変数fに格納されているアドレスは%p", f)
}
//変数fに格納されているアドレスは0xc000094018
最終行に書いてあるような16進数で表現されるのがアドレスで、ポインタを使用することでメモリに自由自在にアクセスすることができるようになります。
次にgolang
におけるポインタの書き方を解説していきます
ポインタの書き方
結論から言うと、&
を使用することでポインタを使用することができます。
先程のコードよりもう少し簡単なコードを記述してみましょう
package main
import "fmt"
func main() {
var a string = "こんにちは!"
var b = &a
fmt.Println(a)
// こんにちは!
fmt.Println(&a)
// 0xc00009e210 値は人によって違います
}
最後のあたりで&
が使われています。この記号を使用することで、ポインタを使用することができます。
加えて以下のコードを見てください
package main
import "fmt"
func main() {
var a string = "こんにちは!"
var b = &a
fmt.Println(a)
// こんにちは!
fmt.Println(&a)
// 0xc00009e210 値は人によって違います
fmt.Println(*b)
// こんにちは!
}
最後のfmt.Println(*b)
で変数a
のアドレスの値を取得しています。
アドレスの値を取得するときは、*
を使います。
ここまで読んできた方でメモリに自在にアクセスできるポインタの何が嬉しいの?って思いますよね。
次のセクションでそれを解説してきます
ポインタはなぜ必要なのか
普通に考えたら、「メモリに保持されているアドレスではなく、基本的な値を操作したい」と思いますよね。
ではどうしてポインタが必要なのでしょうか。
以下のコードを見ながら考えていきましょう
package main
import "fmt"
type User struct {
Name string
Post []string
}
func (u User) newPost(){
u.Post = append(u.Post, "こんばんは!今日もいい天気ですね!")
fmt.Println(u)
// {Anna [明日もいい天気です! こんばんは!今日もいい天気ですね!]}
}
func main() {
u := User{Name: "Anna", Post: []string{"明日もいい天気です!"}}
u.newPost()
fmt.Println(u)
// {Anna [明日もいい天気です!]}
}
ここで「あれ?」と思いませんか?
main
関数で変数u
を出力したとき、なんで{Anna [明日もいい天気です!]}
しか取得できたないんだろうと思いませんか?
ここにはポインタが関与してるんです。
ポインタとは、アドレス情報であるメモリにアクセスするためのもの、と1つ前の章で言いました。
ポインタを使うことでデータの値を参照することができます。
しかしながら、中身のデータを変えることはできないんです。
つまり、ポインタのメリットは、予期していない値によって参照するデータが変更されてしまわないようにしながら、データを参照するために使われているんです。
「ポインタはなぜ必要なのか」という問いに答えるとするならば、「データを参照する際に、データが保持されているアドレスを渡して、意図せずにデータが変更されるのを防ぐため」と言うのが答えになります。
以上です。
何か間違いなどありましたら、コメントで教えていただけると幸いです。
【参考文献】