接口值是可比较的。如果两个接口值相等 它们具有相同的动态类型和相等的动态值,或者 值为零。
var err error
var reader io.Reader
据了解,err
和reader
具有不同的动态类型(error
和io.Reader
),因此不可比。
fmt.Println(err == reader)
将导致编译错误:
无效操作:err == reader(错误类型和io.Reader的不匹配)
如果为真,为什么Println
命令对两个变量输出相同的结果?为什么两者都是nil
?
fmt.Printf("reader: %T", reader) // nil
fmt.Printf("error: %T", err) // nil
EDIT (reflect.TypeOf(err)
或reflect.TypeOf(reader)
)也将输出nil
。我不明白如果类型不同,为什么输出也一样。
答案 0 :(得分:3)
的确,接口值是可比较的,但是您只能比较可分配给彼此的值(更准确地说,一个可分配给另一个)。引用自Spec: Comparison operators:
在任何比较中,第一个操作数必须为第二个操作数的类型的assignable,反之亦然。
您不能将error
的值分配给io.Reader
,也不能将io.Reader
的值分配给error
,所以您也不能比较它们。
如果您想比较它们,它们可能会或可能不会存储相同的动态值,请先将两者都隐瞒interface{}
,以便您可以对它们进行比较,例如:
fmt.Println(interface{}(err) == interface{}(reader))
这将输出(在Go Playground上尝试):
true
注意:实际上,仅将其中一个转换为interface{}
就足够了,因为那样的话,另一个值将与您转换为interface{}
的类型的值相当(任何值可以转换为interface{}
),因此这样做也足够了:
fmt.Println(interface{}(err) == reader)
使用非nil
接口值测试比较:
type x int
func (x) Error() string { return "" }
func (x) Read([]byte) (int, error) { return 0, nil }
err = x(0)
reader = x(0)
fmt.Println(interface{}(err) == interface{}(reader))
reader = x(1)
fmt.Println(interface{}(err) == interface{}(reader))
现在将输出(在Go Playground上尝试):
true
false
也不要忘记nil
接口值不等于保持nil
动态值的非nil
接口值。有关详细信息,请参见Hiding nil values, understanding why golang fails here
编辑:
fmt
包在接口内部打印值,而不是接口值。引用fmt
软件包的文档:
无论动词如何,如果操作数是接口值,则使用内部具体值,而不是接口本身。
与reflect.TypeOf()
相同:它返回动态类型,但是如果您向其传递一个nil
接口值,它将返回nil
,因此将打印fmt
包nil
。引用其文档:
TypeOf返回表示i的动态类型的反射类型。如果i是一个nil接口值,则TypeOf返回nil。