LoginSignup
1
0

More than 1 year has passed since last update.

値レシーバとポインタレシーバの違いについての備忘録(new UserとUser{}を使った場合について)

Last updated at Posted at 2021-09-19

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に格納して利用すれば良い。


参考記事
Goのstructやレシーバについての備忘録

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