8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-01-18

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

以下のように、フィールドに対応する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())
}
8
2
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
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?