Go言語の問題を解いていてポインタの使い方で苦戦した。
深い理解を目指していろいろ調べた備忘録。
問題内容
次のプログラムは、自身を1つずつ加算するメソッドIncを実装したつもりですが、
実際にはうまく動きません。意図通りに動くように修正してください。
また、動かない理由も説明してください。
package main
type Int int
func (n Int) Inc() {
n++
}
func main() {
var n Int
println(n) // 0
n.Inc()
println(n) // 0
}
メソッドの中で+1してるのに、println(n)で0のままになってしまうという状態。
ポインタを使って、メソッド内の変数を参照する
package main
type Int int
// グローバルなデータ型であるintではメソッドを定義することができない(Goの仕様)
// int型のIntをエイリアスとして定義
func (a *Int) Inc() {
// *Intでポインタを宣言することで,main()関数の中のInt型の変数nが
// Inc()メソッドの中のInt型の変数aを参照することができる。
println(a) // 0x1042ffa0 -(1)
println(&a) // 0x1042ffa4 -(2)
// この時点で、aにnのアドレスが渡されている
*a++
// *をaに付与することで、main()のnが参照している値(a)を呼び出すことができる
}
func main() {
var n Int
println(n) // 0
n.Inc() // nの値が、参照先であるaが持つ値(1)に書き換わる
println(n) // 1
}
メソッドには返り値がないため、メソッド内の変数にポインタを定義して
main()側から参照できる形にする必要がある。
アドレス演算子の有無でアドレスの出力変わるのは、なぜだろう...??
ポインタを使わずに書いた場合
返り値のデータ型を定義して、returnさせてみた。
package main
type Int int
func (a Int) Inc() Int {
a++
return a
}
func main() {
var n Int
println(n) // 0
var b = n.Inc()
println(b) // 1
}