Golang中空接口的比较

Golang中空接口的比较,go,interface,comparison,Go,Interface,Comparison,根据 界面值具有可比性。两个接口值相等,如果 它们具有相同的动态类型和相同的动态值,或者两者都具有 价值为零 据了解,err和reader具有不同的动态类型(error和io.reader),因此不具有可比性 fmt.Println(err == reader) 将导致编译错误: 无效操作:err==读取器(错误和io.reader类型不匹配) 如果为真,为什么Println命令为两个变量输出相同的结果?为什么两者都是零 fmt.Printf("reader: %T", reader) //

根据

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

据了解,
err
reader
具有不同的动态类型(
error
io.reader
),因此不具有可比性

fmt.Println(err == reader) 
将导致编译错误:

无效操作:err==读取器(错误和io.reader类型不匹配)

如果为真,为什么
Println
命令为两个变量输出相同的结果?为什么两者都是零

fmt.Printf("reader: %T", reader) // nil
fmt.Printf("error: %T", err) // nil

编辑
reflect.TypeOf(err)
reflect.TypeOf(reader)
也将输出
nil
。如果类型不同,我不理解为什么输出是相同的。

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

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

您不能将
错误
值分配给
io.Reader
,也不能将
io.Reader
值分配给
错误
,因此无法对它们进行比较

它们可能存储相同的动态值,也可能不存储相同的动态值。如果要比较这些值,请首先将两者转换为
接口{}
,以便进行比较,例如:

fmt.Println(interface{}(err) == interface{}(reader))
这将输出(在上尝试):

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

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))
现在输出将是(在上尝试):

另外,不要忘记
nil
接口值并不等于持有
nil
动态值的非
nil
接口值。有关详细信息,请参阅

编辑:

包打印接口内的值,而不是接口值。从
fmt
的包装文件中报价:

不管动词是什么,如果操作数是接口值,则使用内部具体值,而不是接口本身

与此相同:它返回动态类型,但如果您将
nil
接口值传递给它,它将返回
nil
,因此
fmt
包将打印
nil
。引用其文件:

TypeOf返回表示i的动态类型的反射类型。如果i是nil接口值,则TypeOf返回nil


的确,接口值是可比较的,但您只能比较可相互分配的值(更准确地说,一个值可分配给另一个值)。引用

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

您不能将
错误
值分配给
io.Reader
,也不能将
io.Reader
值分配给
错误
,因此无法对它们进行比较

它们可能存储相同的动态值,也可能不存储相同的动态值。如果要比较这些值,请首先将两者转换为
接口{}
,以便进行比较,例如:

fmt.Println(interface{}(err) == interface{}(reader))
这将输出(在上尝试):

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

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))
现在输出将是(在上尝试):

另外,不要忘记
nil
接口值并不等于持有
nil
动态值的非
nil
接口值。有关详细信息,请参阅

编辑:

包打印接口内的值,而不是接口值。从
fmt
的包装文件中报价:

不管动词是什么,如果操作数是接口值,则使用内部具体值,而不是接口本身

与此相同:它返回动态类型,但如果您将
nil
接口值传递给它,它将返回
nil
,因此
fmt
包将打印
nil
。引用其文件:

TypeOf返回表示i的动态类型的反射类型。如果i是nil接口值,则TypeOf返回nil


谢谢你的回答!我编辑了我的问题来澄清这一点,你能看一下吗?但是如果
读取器
error
的动态类型相同(
nil
),为什么它们不可比较呢?@AyZu,因为它们都不可分配给另一个(它们有不同的静态类型:
error
io.reader
)。规范要求单向可分配。好的,谢谢!我混淆了静态类型和动态类型。它们具有相同的动态类型
nil
,因此
reflect.TypeOf()
输出相同的结果,但它们具有不同的静态类型,因此不具有可比性。谢谢您的回答!我编辑了我的问题来澄清这一点,你能看一下吗?但是如果
读取器
error
的动态类型相同(
nil
),为什么它们不可比较呢?@AyZu,因为它们都不可分配给另一个(它们有不同的静态类型:
error
io.reader
)。规范要求单向可分配。好的,谢谢!我混淆了静态类型和动态类型。它们具有相同的动态类型
nil
,因此