Commit c40bffd9 authored by Romain Baugue's avatar Romain Baugue Committed by Ian Lance Taylor

reflect: add Value.IsZero

Fixes #7501

Change-Id: Iac7c79cd4b30a90b14ed84bf1eba758972232a6c
Reviewed-on: https://go-review.googlesource.com/c/go/+/171337
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 6d64dd73
......@@ -1061,6 +1061,113 @@ func TestIsNil(t *testing.T) {
NotNil(fi, t)
}
func TestIsZero(t *testing.T) {
for i, tt := range []struct {
x interface{}
want bool
}{
// Booleans
{true, false},
{false, true},
// Numeric types
{int(0), true},
{int(1), false},
{int8(0), true},
{int8(1), false},
{int16(0), true},
{int16(1), false},
{int32(0), true},
{int32(1), false},
{int64(0), true},
{int64(1), false},
{uint(0), true},
{uint(1), false},
{uint8(0), true},
{uint8(1), false},
{uint16(0), true},
{uint16(1), false},
{uint32(0), true},
{uint32(1), false},
{uint64(0), true},
{uint64(1), false},
{float32(0), true},
{float32(1.2), false},
{float64(0), true},
{float64(1.2), false},
{math.Copysign(0, -1), false},
{complex64(0), true},
{complex64(1.2), false},
{complex128(0), true},
{complex128(1.2), false},
{complex(math.Copysign(0, -1), 0), false},
{complex(0, math.Copysign(0, -1)), false},
{complex(math.Copysign(0, -1), math.Copysign(0, -1)), false},
{uintptr(0), true},
{uintptr(128), false},
// Array
{Zero(TypeOf([5]string{})).Interface(), true},
{[5]string{"", "", "", "", ""}, true},
{[5]string{}, true},
{[5]string{"", "", "", "a", ""}, false},
// Chan
{(chan string)(nil), true},
{make(chan string), false},
{time.After(1), false},
// Func
{(func())(nil), true},
{New, false},
// Interface
{New(TypeOf(new(error)).Elem()).Elem(), true},
{(io.Reader)(strings.NewReader("")), false},
// Map
{(map[string]string)(nil), true},
{map[string]string{}, false},
{make(map[string]string), false},
// Ptr
{(*func())(nil), true},
{(*int)(nil), true},
{new(int), false},
// Slice
{[]string{}, false},
{([]string)(nil), true},
{make([]string, 0), false},
// Strings
{"", true},
{"not-zero", false},
// Structs
{T{}, true},
{T{123, 456.75, "hello", &_i}, false},
// UnsafePointer
{(unsafe.Pointer)(nil), true},
{(unsafe.Pointer)(new(int)), false},
} {
var x Value
if v, ok := tt.x.(Value); ok {
x = v
} else {
x = ValueOf(tt.x)
}
b := x.IsZero()
if b != tt.want {
t.Errorf("%d: IsZero((%s)(%+v)) = %t, want %t", i, x.Kind(), tt.x, b, tt.want)
}
if !Zero(TypeOf(tt.x)).IsZero() {
t.Errorf("%d: IsZero(Zero(TypeOf((%s)(%+v)))) is false", i, x.Kind(), tt.x)
}
}
func() {
defer func() {
if r := recover(); r == nil {
t.Error("should panic for invalid value")
}
}()
(Value{}).IsZero()
}()
}
func TestInterfaceExtraction(t *testing.T) {
var s struct {
W io.Writer
......
......@@ -1071,6 +1071,46 @@ func (v Value) IsValid() bool {
return v.flag != 0
}
// IsZero reports whether v is a zero value for its type.
// It panics if the argument is invalid.
func (v Value) IsZero() bool {
switch v.kind() {
case Bool:
return !v.Bool()
case Int, Int8, Int16, Int32, Int64:
return v.Int() == 0
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return v.Uint() == 0
case Float32, Float64:
return math.Float64bits(v.Float()) == 0
case Complex64, Complex128:
c := v.Complex()
return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
case Array:
for i := 0; i < v.Len(); i++ {
if !v.Index(i).IsZero() {
return false
}
}
return true
case Chan, Func, Interface, Map, Ptr, Slice, UnsafePointer:
return v.IsNil()
case String:
return v.Len() == 0
case Struct:
for i := 0; i < v.NumField(); i++ {
if !v.Field(i).IsZero() {
return false
}
}
return true
default:
// This should never happens, but will act as a safeguard for
// later, as a default value doesn't makes sense here.
panic(&ValueError{"reflect.Value.IsZero", v.Kind()})
}
}
// Kind returns v's Kind.
// If v is the zero Value (IsValid returns false), Kind returns Invalid.
func (v Value) Kind() Kind {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment