因为不是所有类型都可以进行比较,例如切片。所以我们不能这样做。
var v ArbitraryType
v == reflect.Zero(reflect.TypeOf(v)).Interface()
因为不是所有类型都可以进行比较,例如切片。所以我们不能这样做。
var v ArbitraryType
v == reflect.Zero(reflect.TypeOf(v)).Interface()
Go 1.13引入了reflect
包中的Value.IsZero
方法。以下是使用它来检查零值的方法:
if reflect.ValueOf(v).IsZero() {
// v is zero, do something
}
这取决于你希望在接口 v
时产生什么行为(对于其他类型也是一样):
reflect.ValueOf(v).IsZero()
检查接口中包装的值是否为零reflect.ValueOf(&v).Elem().IsZero()
检查接口变量是否为零演示 (playground):
var v interface{} = ""
fmt.Println(reflect.ValueOf(v).IsZero()) // true, the empty string "" is zero
fmt.Println(reflect.ValueOf(&v).Elem().IsZero()) // false, the interface itself is not zero
ValueOf
的参数是 interface{}
。如果传递一个接口,它将取消封装其中的动态值。Go 的 ValueOf
文档提醒:
通过使用ValueOf 返回一个新的 Value,其初始化为 接口 i 中存储的具体值
ValueOf(&v)
,"接口 i 中存储的具体值" 将成为指向 v
的指针。然后你可以使用 Elem()
解引用得到原始值,最后检查 IsZero()
。reflect.ValueOf(&v).Elem().IsZero()
,但你可能因情况而异。
var zero T
或 *new(T)
运用 ==
运算符来检查变量是否为零值。类型参数必须是可比较的 (comparable
约束或可比较类型集)。func IsZeroVar[T ~int64 | ~string](v T) bool {
var zero T
return v == zero
}
func IsZeroNew[T ~int64 | ~string](v T) bool {
return v == *new(T)
}
reflect
包非常简单:func IsZero(v interface{}) (bool, error) {
t := reflect.TypeOf(v)
if !t.Comparable() {
return false, fmt.Errorf("type is not comparable: %v", t)
}
return v == reflect.Zero(t).Interface(), nil
}
这里有一个示例使用。
reflect.ValueOf(v) == reflect.Zero(reflect.TypeOf(v)))
reflect.DeepEqual(reflect.ValueOf(v), reflect.Zero(reflect.TypeOf(v)))
例如,各种整数0的类型和未初始化的struct
都是“零”。
遗憾的是,空字符串和数组不是。而nil
会导致异常。
如果需要,您可以特殊处理这些情况。