2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Golangにおけるポインタの必要性を理解したのでその解説

Last updated at Posted at 2022-09-09

今までRoRやPHPなどの動的型付言語をメインでやってきたんですが、今回行っているインターン先で、Goを使うことになったので、勉強しています。

そのなかで、初めて知った概念であるポインタについて今回は解説していこうと思います。

今回の記事を読んでわかることは以下の3つです。

  • ポインタとはなんなのか
  • ポインタの書き方
  • ポインタってなぜ必要なのか

この2つがわかるようになると思いますので、最後までお付き合いお願いいたします。

なお、この記事では公式のPlayGroundからハンズオンでコピペではなく、手を動かしてみるのをお勧めします

ポインタとは何なのか?

簡潔に言えば、ポインタとはアドレス情報であるメモリにアクセスするためのものです。
メモリとは一時的にデータが保存されている場所でその中に変数が保存されています。

メモリについてはこちらの記事が参考になるのでぜひ。

例として以下のコードを見てください

main.go
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におけるポインタの書き方を解説していきます

ポインタの書き方

結論から言うと、&を使用することでポインタを使用することができます。
先程のコードよりもう少し簡単なコードを記述してみましょう

main.go
package main

import "fmt"

func main() {
    var a string = "こんにちは!"
    var b = &a

    fmt.Println(a)
    // こんにちは!
    fmt.Println(&a)
    // 0xc00009e210 値は人によって違います
}

最後のあたりで&が使われています。この記号を使用することで、ポインタを使用することができます。
加えて以下のコードを見てください

main.go
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のアドレスの値を取得しています。
アドレスの値を取得するときは、*を使います。

ここまで読んできた方でメモリに自在にアクセスできるポインタの何が嬉しいの?って思いますよね。
次のセクションでそれを解説してきます

ポインタはなぜ必要なのか

普通に考えたら、「メモリに保持されているアドレスではなく、基本的な値を操作したい」と思いますよね。
ではどうしてポインタが必要なのでしょうか。
以下のコードを見ながら考えていきましょう

main.go
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つ前の章で言いました。

ポインタを使うことでデータの値を参照することができます。
しかしながら、中身のデータを変えることはできないんです。

つまり、ポインタのメリットは、予期していない値によって参照するデータが変更されてしまわないようにしながら、データを参照するために使われているんです。

「ポインタはなぜ必要なのか」という問いに答えるとするならば、「データを参照する際に、データが保持されているアドレスを渡して、意図せずにデータが変更されるのを防ぐため」と言うのが答えになります。

以上です。
何か間違いなどありましたら、コメントで教えていただけると幸いです。

【参考文献】

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?