aboutsummaryrefslogtreecommitdiff
path: root/src/reflect/value.go
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2021-10-24 14:11:07 +1100
committerRob Pike <r@golang.org>2021-10-29 02:11:42 +0000
commit33c392f72d16163eb0795b3d61b2196ac21e1799 (patch)
tree2121c6ed2c08c00b93f3eec8f27d950dae6c1091 /src/reflect/value.go
parentaf05d8be3d9dd566b2ce3ff5344258314f128ff6 (diff)
downloadgo-33c392f72d16163eb0795b3d61b2196ac21e1799.tar.gz
go-33c392f72d16163eb0795b3d61b2196ac21e1799.zip
reflect: add FieldByIndexErr
This new function, although different in signature from other reflect functions, allows the caller to avoid the panic caused by nil embedded fields in calls to FieldByIndex. Fixes #48218 Change-Id: I447f135bb789148c27ae3f2f23dcf43094f4c1de Reviewed-on: https://go-review.googlesource.com/c/go/+/357962 Trust: Rob Pike <r@golang.org> Run-TryBot: Rob Pike <r@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/reflect/value.go')
-rw-r--r--src/reflect/value.go27
1 files changed, 26 insertions, 1 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 618d38893e..90edf8e31d 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -5,6 +5,7 @@
package reflect
import (
+ "errors"
"internal/abi"
"internal/goarch"
"internal/itoa"
@@ -1232,7 +1233,8 @@ func (v Value) Field(i int) Value {
}
// FieldByIndex returns the nested field corresponding to index.
-// It panics if v's Kind is not struct.
+// It panics if evaluation requires stepping through a nil
+// pointer or a field that is not a struct.
func (v Value) FieldByIndex(index []int) Value {
if len(index) == 1 {
return v.Field(index[0])
@@ -1252,6 +1254,29 @@ func (v Value) FieldByIndex(index []int) Value {
return v
}
+// FieldByIndexErr returns the nested field corresponding to index.
+// It returns an error if evaluation requires stepping through a nil
+// pointer, but panics if it must step through a field that
+// is not a struct.
+func (v Value) FieldByIndexErr(index []int) (Value, error) {
+ if len(index) == 1 {
+ return v.Field(index[0]), nil
+ }
+ v.mustBe(Struct)
+ for i, x := range index {
+ if i > 0 {
+ if v.Kind() == Ptr && v.typ.Elem().Kind() == Struct {
+ if v.IsNil() {
+ return Value{}, errors.New("reflect: indirection through nil pointer to embedded struct field " + v.typ.Elem().Name())
+ }
+ v = v.Elem()
+ }
+ }
+ v = v.Field(x)
+ }
+ return v, nil
+}
+
// FieldByName returns the struct field with the given name.
// It returns the zero Value if no field was found.
// It panics if v's Kind is not struct.