Closed
Description
This makes exported fields in unexported anonymous field not settable
What version of Go are you using (go version
)?
$ go version go version go1.12.6 darwin/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GOARCH="amd64" GOBIN="" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOOS="darwin" GOPROXY="" GORACE="" GOROOT="/usr/local/Cellar/go/1.12.6/libexec" GOTMPDIR="" GOTOOLDIR="/usr/local/Cellar/go/1.12.6/libexec/pkg/tool/darwin_amd64" GCCGO="gccgo" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/b6/81wsy1517sxdpkd09pwj98_w0000gn/T/go-build799570696=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
https://play.golang.org/p/mKRa1-3j2He
package main
import (
"fmt"
"reflect"
)
type embed struct{ X int }
type S1 struct {
embed
}
func printCanSet(value reflect.Value, index []int) {
current := value
for _, i := range index {
if i == -1 {
// Addr() decays flagRO, which is a combination of flagEmbedRO and flagStickyRO, to flagStickyRO which is propagated to
// all nested fields, thus making exported fields in unexported anonymous field not settable.
//
// See for implementation details:
// * https://github.com/golang/go/blob/master/src/reflect/value.go#L83
// * https://github.com/golang/go/blob/master/src/reflect/value.go#L256
// * https://github.com/golang/go/blob/master/src/reflect/value.go#L829
current = current.Addr().Elem()
} else {
current = current.Field(i)
}
}
fmt.Printf("Value %+v lookup index %+v: CanSet ? %t\n", value, index, current.CanSet())
}
func main() {
value := reflect.ValueOf(&S1{}).Elem()
printCanSet(value, []int{0, 0})
printCanSet(value, []int{0, -1, 0})
}
What did you expect to see?
The second should prints true
for CanSet
.
What did you see instead?
The second prints false
for CanSet
.
See also
- 6471ace#diff-299545bcc665f75feeed30dce79b50ecR243 introduced this behavior.
- I have present a trial fix in https://github.com/kezhuw/go/commits/fix-reflect-addr-lost-embed-ro, it contains two commits:
- The first commit (kezhuw/go@f403764) introduces changes to break
TestCanSetField
in go. - The second commit (kezhuw/go@376b342) fixes breaking tests caused by previous commit.
- The first commit (kezhuw/go@f403764) introduces changes to break