36

我有一个int/ string/ bool/etc.. 值存储在 an 中interface{},并想确定它是否未初始化,这意味着它的值是

  • 0
  • ""
  • false
  • 或者nil

我该如何检查?

4

4 回答 4

76

据我了解,你想要这样的东西:

func IsZeroOfUnderlyingType(x interface{}) bool {
    return x == reflect.Zero(reflect.TypeOf(x)).Interface()
}

在谈论接口和nil时,人们总是对两个非常不同且不相关的东西感到困惑:

  1. 一个nil接口值,它是一个没有基础值的接口值。这是接口类型的零值。
  2. 一个非nil接口值(即它有一个基础值),但它的基础值是其基础类型的零值。例如,基础值是nil映射、nil指针或 0 数字等。

我的理解是你问的是第二件事。


更新:由于上面的代码使用==,它不适用于不可比较的类型。我相信使用reflect.DeepEqual()相反会使它适用于所有类型:

func IsZeroOfUnderlyingType(x interface{}) bool {
    return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}
于 2012-12-16T22:18:47.210 回答
16

Go 1.13(2019 年第三季度)应该简化检测过程:

Value.IsZero()方法报告 Value 是否是其类型的零值。

它是在提交 c40bffdCL 171337src/reflect/value.go中实现的,解决了问题 7501

请参阅操场示例(只要支持 Go 1.13)

于 2019-08-22T16:20:21.050 回答
4

type的零值*interface{}是 only nil, not 0or ""or false

package main

import "fmt"

func main() {
        var v interface{}
        fmt.Println(v == nil, v == 0, v == "", v == false)
}

(也http://play.golang.org/p/z1KbX1fOgB


输出

true false false false

*: [Q]当内存被分配来存储一个值时,无论是通过声明还是调用make或new,并且没有提供显式初始化,内存被赋予默认初始化。这样一个值的每个元素都被设置为零值:布尔值为 false,整数为 0,浮点数为 0.0,字符串为 "",指针、函数、接口、切片、通道和映射为 nil。 /问]

于 2012-12-16T13:45:26.037 回答
0

@newacct 的答案无法检测到原始零值,调用reflect.Value.Interface()它会导致错误。它可以reflect.Value.IsValid()用来检查。

// IsValid reports whether v represents a value.
// It returns false if v is the zero Value.
// If IsValid returns false, all other methods except String panic.
// Most functions and methods never return an invalid value.
// If one does, its documentation states the conditions explicitly.
func (v Value) IsValid() bool 

更新方法:

func IsZero(v reflect.Value) bool {
    return !v.IsValid() || reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
}

func TestIsZero(t *testing.T) {
    var p *string
    v := reflect.ValueOf(p)

    assert.Equal(t, true, v.IsValid())
    assert.True(t, IsZero(v))

    assert.Equal(t, uintptr(0), v.Pointer())

    v = v.Elem()
    assert.Equal(t, false, v.IsValid())
    assert.True(t, IsZero(v))
}
于 2019-03-01T06:18:32.690 回答