diff options
author | cuiweixie <cuiweixie@gmail.com> | 2022-04-25 05:21:35 +0000 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2022-04-25 23:18:00 +0000 |
commit | 892cd0b63638ec856e6fef1bdaaa20a177695fea (patch) | |
tree | 81aaa669d9374e17520c48b07601b7b5c1a1e370 | |
parent | 35f2aba2830483270249d4f34250e38af88bd33d (diff) | |
download | go-git-892cd0b63638ec856e6fef1bdaaa20a177695fea.tar.gz |
reflect: support Len and Cap on pointer-to-array Value
Fixes #52411
Change-Id: I2fd13a453622992c52d49aade7cd058cfc8a77ca
GitHub-Last-Rev: d5987c2ec817ebd01d9e1adb3bd2e75274dbbabd
GitHub-Pull-Request: golang/go#52423
Reviewed-on: https://go-review.googlesource.com/c/go/+/400954
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Keith Randall <khr@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
-rw-r--r-- | src/reflect/all_test.go | 66 | ||||
-rw-r--r-- | src/reflect/value.go | 14 |
2 files changed, 78 insertions, 2 deletions
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 72d01c7deb..9eb01bde35 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7913,3 +7913,69 @@ func BenchmarkSliceCap(b *testing.B) { sinkAll.RawInt = sourceAll.SliceAny.Cap() } } + +func TestValue_Cap(t *testing.T) { + a := &[3]int{1, 2, 3} + v := ValueOf(a) + if v.Cap() != cap(a) { + t.Errorf("Cap = %d want %d", v.Cap(), cap(a)) + } + + a = nil + v = ValueOf(a) + if v.Cap() != cap(a) { + t.Errorf("Cap = %d want %d", v.Cap(), cap(a)) + } + + getError := func(f func()) (errorStr string) { + defer func() { + e := recover() + if str, ok := e.(string); ok { + errorStr = str + } + }() + f() + return + } + e := getError(func() { + var ptr *int + ValueOf(ptr).Cap() + }) + wantStr := "reflect: call of reflect.Value.Cap on ptr to non-array Value" + if e != wantStr { + t.Errorf("error is %q, want %q", e, wantStr) + } +} + +func TestValue_Len(t *testing.T) { + a := &[3]int{1, 2, 3} + v := ValueOf(a) + if v.Len() != len(a) { + t.Errorf("Len = %d want %d", v.Len(), len(a)) + } + + a = nil + v = ValueOf(a) + if v.Len() != len(a) { + t.Errorf("Len = %d want %d", v.Len(), len(a)) + } + + getError := func(f func()) (errorStr string) { + defer func() { + e := recover() + if str, ok := e.(string); ok { + errorStr = str + } + }() + f() + return + } + e := getError(func() { + var ptr *int + ValueOf(ptr).Len() + }) + wantStr := "reflect: call of reflect.Value.Len on ptr to non-array Value" + if e != wantStr { + t.Errorf("error is %q, want %q", e, wantStr) + } +} diff --git a/src/reflect/value.go b/src/reflect/value.go index 6b5ebfae24..f92fa16fe6 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1144,7 +1144,7 @@ func funcName(f func([]Value) []Value) string { } // Cap returns v's capacity. -// It panics if v's Kind is not Array, Chan, or Slice. +// It panics if v's Kind is not Array, Chan, Slice or pointer to Array. func (v Value) Cap() int { // capNonSlice is split out to keep Cap inlineable for slice kinds. if v.kind() == Slice { @@ -1160,6 +1160,11 @@ func (v Value) capNonSlice() int { return v.typ.Len() case Chan: return chancap(v.pointer()) + case Ptr: + if v.typ.Elem().Kind() == Array { + return v.typ.Elem().Len() + } + panic("reflect: call of reflect.Value.Cap on ptr to non-array Value") } panic(&ValueError{"reflect.Value.Cap", v.kind()}) } @@ -1600,7 +1605,7 @@ func (v Value) Kind() Kind { } // Len returns v's length. -// It panics if v's Kind is not Array, Chan, Map, Slice, or String. +// It panics if v's Kind is not Array, Chan, Map, Slice, String, or pointer to Array. func (v Value) Len() int { // lenNonSlice is split out to keep Len inlineable for slice kinds. if v.kind() == Slice { @@ -1621,6 +1626,11 @@ func (v Value) lenNonSlice() int { case String: // String is bigger than a word; assume flagIndir. return (*unsafeheader.String)(v.ptr).Len + case Ptr: + if v.typ.Elem().Kind() == Array { + return v.typ.Elem().Len() + } + panic("reflect: call of reflect.Value.Len on ptr to non-array Value") } panic(&ValueError{"reflect.Value.Len", v.kind()}) } |