【问题标题】:Comparison between empty interfaces in GolangGolang中空接口的比较
【发布时间】:2019-01-02 08:28:25
【问题描述】:

根据specification:

接口值具有可比性。两个接口值相等,如果 它们具有相同的动态类型和相同的动态值,或者如果两者都有 值为零。

var err error 
var reader io.Reader                           

据了解,errreader 具有不同的动态类型(errorio.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。我不明白如果类型不同,为什么输出是相同的。

【问题讨论】:

    标签: go interface comparison


    【解决方案1】:

    确实,接口值是可比较的,但您只能比较可分配给彼此的值(更准确地说,一个可分配给另一个)。引用自Spec: Comparison operators:

    在任何比较中,第一个操作数必须是 assignable 到第二个操作数的类型,反之亦然。

    您不能将error 值分配给io.Reader,也不能将io.Reader 值分配给error,因此您无法比较它们。

    它们可能存储也可能不存储相同的动态值,如果你想比较它们,首先将两者都转换为interface{},以便你可以比较它们,例如:

    fmt.Println(interface{}(err) == interface{}(reader))
    

    这将输出(在Go Playground 上尝试):

    true
    

    注意:实际上只将其中一个转换为interface{}就足够了,因为这样另一个值将与您转换为interface{}的类型相当(任何值都可以转换为@ 987654337@),所以这样做也足够了:

    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 的动态类型的反射 Type。如果 i 是 nil 接口值,TypeOf 返回 nil。

    【讨论】:

    • 感谢您的回答!我已经编辑了我的问题以澄清这一点,你能看看吗?
    • 但是如果readererror的动态类型相同(nil)为什么它们没有可比性呢?
    • @AyZu 因为它们都不能分配给另一个(它们有不同的静态类型:errorio.Reader)。而且规范要求单向可分配性。
    • 好的,谢谢!我对静态类型和动态类型感到困惑。它们具有相同的动态类型nil,因此reflect.TypeOf() 输出相同的结果,但它们具有不同的静态类型,因此它们没有可比性。
    猜你喜欢
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-05
    相关资源
    最近更新 更多