読者です 読者をやめる 読者になる 読者になる

DRYな備忘録

Don't Repeat Yourself.

Go言語のfieldがメソッドによって更新されないっぽい?

go

問題

Golangのstructに生えてるメソッドによって、structのfieldを更新しようとしたけど、変わってないっぽい?

package main

import "fmt"

type Ship struct {
    name string
}
func (s Ship) ChangeName() string {
    s.name = s.name + "改"
    return s.name
}
func main() {
    yudachi := Ship{"夕立"}
    fmt.Printf("%+v\n", yudachi)    // 夕立
    var name string
 
    name = yudachi.ChangeName()
    fmt.Println(name)               // 返り値は夕立改
    fmt.Printf("%+v\n", yudachi)    // しかし夕立自身は変わってない
}

なんでっぽい?

原因

structに生えるメソッドの定義には二種類あるっぽい(で、callerにおいてstruct自身がポインタかどうかは問わないっぽい)

// 値が来る
func (s MyStruct) Foo() {
    fmt.Printf("%T", s)    // MyStruct
}
// ポインタで来る
func (s *MyStruct) Bar() {
    fmt.Printf("%T", s)    // *MyStruct
}

解決

package main

import "fmt"

type Ship struct {
    name string
}
func (s Ship) ChangeName() string {
    s.name = s.name + "改"
    // fmt.Printf("%T\n", s)
    return s.name
}
func (s *Ship) ChangeNameMore() string {
    s.name = s.name + "改二"
    // fmt.Printf("%T\n", s)
    return s.name
}
func main() {
    yudachi := Ship{"夕立"}
    // yudachi := &Ship{"夕立"} これでもいい
    fmt.Printf("%T\n", yudachi)
 
    fmt.Printf("%+v\n", yudachi)    // 夕立
    var name string
 
    name = yudachi.ChangeName()
    fmt.Println(name)               // 返り値は夕立改
    fmt.Printf("%+v\n", yudachi)    // しかし夕立自身は変わってない
 
    name = yudachi.ChangeNameMore()
    fmt.Println(name)               // 返り値は夕立改二
    fmt.Printf("%+v\n", yudachi)    // ポインタ渡しなので夕立自身も変わる
}

golangおもしろいっぽい!

DRY