Go初心者で躓いたのでメモとして残します。
type User struct { Name string }
があるとする。
u := new(User)
と、u := User{}
では、値レシーバとポインタレシーバを使う際どう異なるのかを、暗黙の変換に着目してまとめてみた。
package main
import "fmt"
type User struct {
Name string
}
// メソッド(値レシーバ)
func (u User) setValueName() {
u.Name = "gopher"
}
// メソッド(ポインターレシーバ)
func (u *User) setPointerName() {
u.Name = "gopher"
}
func main() {
// 値レシーバ
u1 := new(User) // uは*User型
(*u1).setValueName()
fmt.Println("u1.Name:", u1.Name, "*u1:", *u1, "&u1", &u1)
// u1.Name: *u1: {} &u1 0xc0000b8018
u2 := User{} // u2はUser型
p2 := &u2
(&u2).setValueName()
fmt.Println("u2.Name:", u2.Name, "*u2(p2):", *p2, "&u2:", &u2)
// u2.Name: *u2(p2): {} &u2: &{}
// ポインタレシーバ
u3 := new(User) // u3は*User型
(*u3).setPointerName()
fmt.Println("u3.Name:", u3.Name, "*u3:", *u3, "&u3", &u3)
// u3.Name: gopher *u3: {gopher} &u3 0xc0000b8028
u4 := User{} // u4はUser型
p4 := &u4
(&u4).setPointerName()
fmt.Println("u4.Name:", u4.Name, "*u4(p4):", *p4, "&u4:", &u4)
// u4.Name: gopher *u4(p4): {gopher} &u4: &{gopher}
}
ちなみに、直接 *u2
(または*u4
)とすると以下のエラー文が出てくる:
invalid operation: cannot indirect u2 (variable of type User)
これは、直接u2
のポインタにアクセスしようとしたため起きたエラーである。
したがって、どうしてもu2
経由でu2
のポインタを取得したい場合、以上のように一旦u2
へのポインタを変数p2
に格納して利用すれば良い。