Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

@tenntenn

exportされていないフィールドの値を変更する #golang

公開されていないフィールドの値を変更する

以下のように、フィールドに対応するreflect.Valueのアドレスを元に、reflect.NewAtreflect.Valueを作り直してやれば、reflect.CanSettrueを返すようになり、セットできるようになります。

なお、unsafeを使っているので、Google App Engineでは使えません。

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

type hoge struct {
    n int
}

func main() {
    h := &hoge{n: 100}
    v := reflect.ValueOf(h)
    fv1 := v.Elem().FieldByName("n")
    fmt.Println(fv1.CanSet())

    fv2 := reflect.NewAt(fv1.Type(), unsafe.Pointer(fv1.UnsafeAddr()))
    if fv2.Elem().CanSet() {
        fv2.Elem().SetInt(200)
    }
    fmt.Println(h)
}

型がわかっている場合

追記(2018/01/19):社内から指摘をうけました!

型がわかっている場合は、reflect.NewAtを使わずにできます。

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

type hoge struct {
    n int
}

func main() {
    h := &hoge{n: 100}
    v := reflect.ValueOf(h)
    fv1 := v.Elem().FieldByName("n")
    i := (*int)(unsafe.Pointer(fv1.UnsafeAddr()))
    *i = 200
    fmt.Println(*i)
}

メソッドはどうなのか

以下のように、メソッドは、reflect.CanAddrfalseを返すので、reflect.NewAtが使えないのでダメです。

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

type hoge struct {
    n int
}

func (h hoge) N() int {
    return h.n
}

func main() {
    h := &hoge{n: 100}
    v := reflect.ValueOf(h)
    mv1 := v.Elem().MethodByName("N")
    fmt.Println(mv1.CanSet())
    fmt.Println(mv1.CanAddr()) // false

    mv2 := reflect.NewAt(mv1.Type(), unsafe.Pointer(mv1.UnsafeAddr()))
    if mv2.Elem().CanSet() {
        mv2.Elem().Set(reflect.ValueOf(func() int {
            return 200
        }))
    }
    fmt.Println(h.N())
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
1
Help us understand the problem. What are the problem?