LoginSignup
0
0

More than 1 year has passed since last update.

# 【Go】関数にポインタ引数を渡すメリット(※かなり基礎的なこと)

Posted at

はじめに

書籍「プログラミング言語Go」に以下の説明があります。

ポインタは変数のアドレスを持っていますので、関数へポインタ引数を渡すことで、関数が間接的に渡された変数を更新することができるようになります。

サンプルコードも記載されていましたが、直感的に理解できなかったのでサンプルコードを動かしながら理解を深めた過程が本投稿になります。

本題

以下2つのコードの違いを確認してみました。

①関数に変数 v のアドレスを渡している

// You can edit this code!
// Click here and start typing.
package main

import "fmt"

func main() {
    v := 1
    fmt.Println(incr(&v))
    fmt.Println(incr(&v))
}

func incr(p *int) int {
    *p++
    return *p
}

https://go.dev/play/p/CwocnClX7x1

実行結果
2
3

②関数に変数 v のを渡している

// You can edit this code!
// Click here and start typing.
package main

import "fmt"

func main() {
    v := 1
    fmt.Println(incr(v))
    fmt.Println(incr(v))
}

func incr(p int) int {
    p++
    return p
}

https://go.dev/play/p/yDCGl9VKF9Y

実行結果
2
2

②のコードは理解できました。引数で受け取ったローカル変数をインクリメントする関数なので、常に return 2 となることはわかりました。
では次に①を確認していきます。かなりスマートじゃない方法ですが、printデバッグで処理経過を追ってみました。

// You can edit this code!
// Click here and start typing.
package main

import "fmt"

func main() {
    v := 1
    fmt.Println(&v)
    fmt.Println(incr(&v, "1回目"))
    fmt.Println(v)
    fmt.Println(&v)
    fmt.Println(incr(&v, "2回目"))
}

func incr(p *int, str string) int {
    fmt.Println(str)
    fmt.Println(p)
    fmt.Println(*p)
    *p++
    fmt.Println(*p)
    fmt.Println(p)
    fmt.Println("関数抜ける")
    return *p
}

https://go.dev/play/p/1qtDacPAU1y

0xc0000b8000
1回目
0xc0000b8000
1
2
0xc0000b8000
関数抜ける
2
2
0xc0000b8000
2回目
0xc0000b8000
2
3
0xc0000b8000
関数抜ける
3

常に同じポインタを渡していることがわかりました。冒頭で引用した文章の意味は、ポインタを渡すことで関数 incr が変数 v間接的に更新できることを言っているんですね。やっと引数にポインタを指定する意図を少しだけ理解できた気がします。

参考元

□プログラミング言語Go
https://www.maruzen-publishing.co.jp/item/?book_no=295039

0
0
0

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
0
0