这里的问题是那shower
是一种interface
类型。Go中的接口类型保存实际值及其 动态 类型。关于此的更多详细信息:反射定律#接口的表示。
您返回的切片包含2个非nil
值。第二个值是一个接口值,一个保存nil
指针值的(值;类型)对和一个*display
具体类型。从Go语言规范中引用:比较运算符:
接口值是可比较的。如果两个接口值具有相同的动态类型和相等的动态值,或者两个值都具有value,则它们是相等的nil
。
所以,如果你把它比作nil
,这将是false
。如果将其与代表该对的接口值进行比较(nil;*display)
,则将为true
:
if x == (*display)(nil) { panic("everything ok, nil found") }
@H_419_35@这似乎不可行,因为您必须知道接口所持有的实际类型。但是请注意,您可以使用反射来判断非
nil
接口值是否使用来包装nil
值Value.IsNil()
。您可以在Go Playground上看到一个示例。与其他具体类型不同的接口(非接口)可以容纳不同具体类型的值(不同的静态类型)。运行时需要知道存储在接口类型变量中的值的动态类型或运行时类型。
An
interface
只是一个方法集,如果相同方法属于该类型的方法集的一部分,则任何类型都可以 实现它。有些类型不能为,例如或为其基础类型的自定义类型。在这些情况下,您将不需要能够存储该特定类型的值。nil``struct``int``nil
但是 任何类型 还包括
nil
有效值(例如切片,地图,通道,所有指针类型)的具体类型,因此,为了在运行时存储满足接口要求的值,可以合理地支持nil
在接口内部进行存储。但是除了nil
接口内部,我们还必须存储其动态类型,因为该nil
值不包含此类信息。nil
当要存储在其中的值是时,替代选项将用作接口值本身nil
,但是此解决方案不足,因为它将丢失动态类型信息。有人说Go的接口是动态类型的,但这是误导的。它们是静态类型的:接口类型的变量始终具有相同的静态类型,即使在运行时存储在接口变量中的值可能会更改类型,该值也将始终满足接口的要求。
通常,如果要指示类型
nil
的值interface
,请使用显式nil
值,然后可以测试是否nil
相等。最常见的示例是内置error
类型,它是一种方法的接口。只要没有错误,就可以显式设置或返回值,nil
而不是某些具体(非接口)类型的错误变量的值(这实际上是错误的做法,请参见下面的演示)。在您的示例中,混淆源于以下事实:
- 您想要一个值作为接口类型(
shower
) - 但是您要存储在切片中的值不是类型
shower
而是具体类型
因此,当您将一个*display
类型放入shower
切片中时,将创建一个接口值,该接口值是一对(value;
type),其中value是nil
且type是*display
。该对中的 值
将是nil
,而不是接口值本身。如果您将一个nil
值放入分片中,则接口值 本身 为nil
,条件x == nil
为true
。
请参见以下示例:操场
type MyErr string func (m MyErr) Error() string { return "big fail" } func doSomething(i int) error { switch i { default: return nil // This is the trivial true case case 1: var p *MyErr return p // This will be false case 2: return (*MyErr)(nil) // Same as case 1 case 3: var err error // Zero value is nil for the interface return err // This will be true because err is already interface type case 4: var p *MyErr return error(p) // This will be false because the interface points to a // nil item but is not nil itself. } } func main() { for i := 0; i <= 4; i++ { err := doSomething(i) fmt.Println(i, err, err == nil) } }
@H_419_35@输出:
0 <nil> true 1 <nil> false 2 <nil> false 3 <nil> true 4 <nil> false
@H_419_35@在情况2
nil
中,返回了一个指针,但首先将其转换为接口类型(error
),因此创建了一个接口值,其中包含一个nil
值和该类型*MyErr
,因此该接口值不是nil
。解决方法
我无法理解如何正确确保
nil
在这种情况下不存在某些问题:package main type shower interface { getWater() []shower } type display struct { SubDisplay *display } func (d display) getWater() []shower { return []shower{display{},d.SubDisplay} } func main() { // SubDisplay will be initialized with null s := display{} // water := []shower{nil} water := s.getWater() for _,x := range water { if x == nil { panic("everything ok,nil found") } //first iteration display{} is not nil and will //therefore work,on the second iteration //x is nil,and getWater panics. x.getWater() } }
我发现检查该值是否实际的唯一方法
nil
是使用反射。这真的是想要的行为吗?还是在代码中看不到一些重大错误?
type MyErr string func (m MyErr) Error() string { return "big fail" } func doSomething(i int) error { switch i { default: return nil // This is the trivial true case case 1: var p *MyErr return p // This will be false case 2: return (*MyErr)(nil) // Same as case 1 case 3: var err error // Zero value is nil for the interface return err // This will be true because err is already interface type case 4: var p *MyErr return error(p) // This will be false because the interface points to a // nil item but is not nil itself. } } func main() { for i := 0; i <= 4; i++ { err := doSomething(i) fmt.Println(i, err, err == nil) } }
@H_419_35@输出:
0 <nil> true 1 <nil> false 2 <nil> false 3 <nil> true 4 <nil> false
@H_419_35@在情况2
nil
中,返回了一个指针,但首先将其转换为接口类型(error
),因此创建了一个接口值,其中包含一个nil
值和该类型*MyErr
,因此该接口值不是nil
。解决方法
我无法理解如何正确确保
nil
在这种情况下不存在某些问题:package main type shower interface { getWater() []shower } type display struct { SubDisplay *display } func (d display) getWater() []shower { return []shower{display{},d.SubDisplay} } func main() { // SubDisplay will be initialized with null s := display{} // water := []shower{nil} water := s.getWater() for _,x := range water { if x == nil { panic("everything ok,nil found") } //first iteration display{} is not nil and will //therefore work,on the second iteration //x is nil,and getWater panics. x.getWater() } }
我发现检查该值是否实际的唯一方法
nil
是使用反射。这真的是想要的行为吗?还是在代码中看不到一些重大错误?
0 <nil> true 1 <nil> false 2 <nil> false 3 <nil> true 4 <nil> false
@H_419_35@在情况2
nil
中,返回了一个指针,但首先将其转换为接口类型(error
),因此创建了一个接口值,其中包含一个nil
值和该类型*MyErr
,因此该接口值不是nil
。解决方法
我无法理解如何正确确保
nil
在这种情况下不存在某些问题:package main type shower interface { getWater() []shower } type display struct { SubDisplay *display } func (d display) getWater() []shower { return []shower{display{},d.SubDisplay} } func main() { // SubDisplay will be initialized with null s := display{} // water := []shower{nil} water := s.getWater() for _,x := range water { if x == nil { panic("everything ok,nil found") } //first iteration display{} is not nil and will //therefore work,on the second iteration //x is nil,and getWater panics. x.getWater() } }
我发现检查该值是否实际的唯一方法
nil
是使用反射。这真的是想要的行为吗?还是在代码中看不到一些重大错误?
package main
type shower interface {
getWater() []shower
}
type display struct {
SubDisplay *display
}
func (d display) getWater() []shower {
return []shower{display{},d.SubDisplay}
}
func main() {
// SubDisplay will be initialized with null
s := display{}
// water := []shower{nil}
water := s.getWater()
for _,x := range water {
if x == nil {
panic("everything ok,nil found")
}
//first iteration display{} is not nil and will
//therefore work,on the second iteration
//x is nil,and getWater panics.
x.getWater()
}
}
这似乎不可行,因为您必须知道接口所持有的实际类型。但是请注意,您可以使用反射来判断非nil
接口值是否使用来包装nil
值Value.IsNil()
。您可以在Go
Playground上看到一个示例。
与其他具体类型不同的接口(非接口)可以容纳不同具体类型的值(不同的静态类型)。运行时需要知道存储在接口类型变量中的值的动态类型或运行时类型。
Aninterface
只是一个方法集,如果相同方法属于该类型的方法集的一部分,则任何类型都可以
实现它。有些类型不能为,例如或为其基础类型的自定义类型。在这些情况下,您将不需要能够存储该特定类型的值。nil``struct``int``nil
但是 任何类型
还包括nil
有效值(例如切片,地图,通道,所有指针类型)的具体类型,因此,为了在运行时存储满足接口要求的值,可以合理地支持nil
在接口内部进行存储。但是除了nil
接口内部,我们还必须存储其动态类型,因为该nil
值不包含此类信息。nil
当要存储在其中的值是时,替代选项将用作接口值本身nil
,但是此解决方案不足,因为它将丢失动态类型信息。
有人说Go的接口是动态类型的,但这是误导的。它们是静态类型的:接口类型的变量始终具有相同的静态类型,即使在运行时存储在接口变量中的值可能会更改类型,该值也将始终满足接口的要求。
通常,如果要指示类型nil
的值interface
,请使用显式nil
值,然后可以测试是否nil
相等。最常见的示例是内置error
类型,它是一种方法的接口。只要没有错误,就可以显式设置或返回值,nil
而不是某些具体(非接口)类型的错误变量的值(这实际上是错误的做法,请参见下面的演示)。
在您的示例中,混淆源于以下事实:
因此,当您将一个*display
类型放入shower
切片中时,将创建一个接口值,该接口值是一对(value;
type),其中value是nil
且type是*display
。该对中的 值
将是nil
,而不是接口值本身。如果您将一个nil
值放入分片中,则接口值 本身 为nil
,条件x == nil
为true
。
请参见以下示例:操场
输出:
在情况2nil
中,返回了一个指针,但首先将其转换为接口类型(error
),因此创建了一个接口值,其中包含一个nil
值和该类型*MyErr
,因此该接口值不是nil
。
我无法理解如何正确确保nil
在这种情况下不存在某些问题:
我发现检查该值是否实际的唯一方法nil
是使用反射。
这真的是想要的行为吗?还是在代码中看不到一些重大错误?
这似乎不可行,因为您必须知道接口所持有的实际类型。但是请注意,您可以使用反射来判断非nil
接口值是否使用来包装nil
值Value.IsNil()
。您可以在Go
Playground上看到一个示例。
与其他具体类型不同的接口(非接口)可以容纳不同具体类型的值(不同的静态类型)。运行时需要知道存储在接口类型变量中的值的动态类型或运行时类型。
Aninterface
只是一个方法集,如果相同方法属于该类型的方法集的一部分,则任何类型都可以
实现它。有些类型不能为,例如或为其基础类型的自定义类型。在这些情况下,您将不需要能够存储该特定类型的值。nil``struct``int``nil
但是 任何类型
还包括nil
有效值(例如切片,地图,通道,所有指针类型)的具体类型,因此,为了在运行时存储满足接口要求的值,可以合理地支持nil
在接口内部进行存储。但是除了nil
接口内部,我们还必须存储其动态类型,因为该nil
值不包含此类信息。nil
当要存储在其中的值是时,替代选项将用作接口值本身nil
,但是此解决方案不足,因为它将丢失动态类型信息。
有人说Go的接口是动态类型的,但这是误导的。它们是静态类型的:接口类型的变量始终具有相同的静态类型,即使在运行时存储在接口变量中的值可能会更改类型,该值也将始终满足接口的要求。
通常,如果要指示类型nil
的值interface
,请使用显式nil
值,然后可以测试是否nil
相等。最常见的示例是内置error
类型,它是一种方法的接口。只要没有错误,就可以显式设置或返回值,nil
而不是某些具体(非接口)类型的错误变量的值(这实际上是错误的做法,请参见下面的演示)。
在您的示例中,混淆源于以下事实:
因此,当您将一个*display
类型放入shower
切片中时,将创建一个接口值,该接口值是一对(value;
type),其中value是nil
且type是*display
。该对中的 值
将是nil
,而不是接口值本身。如果您将一个nil
值放入分片中,则接口值 本身 为nil
,条件x == nil
为true
。
请参见以下示例:操场
type MyErr string func (m MyErr) Error() string { return "big fail" } func doSomething(i int) error { switch i { default: return nil // This is the trivial true case case 1: var p *MyErr return p // This will be false case 2: return (*MyErr)(nil) // Same as case 1 case 3: var err error // Zero value is nil for the interface return err // This will be true because err is already interface type case 4: var p *MyErr return error(p) // This will be false because the interface points to a // nil item but is not nil itself. } } func main() { for i := 0; i <= 4; i++ { err := doSomething(i) fmt.Println(i, err, err == nil) } }
@H_419_35@输出:
0 <nil> true 1 <nil> false 2 <nil> false 3 <nil> true 4 <nil> false
@H_419_35@在情况2
nil
中,返回了一个指针,但首先将其转换为接口类型(error
),因此创建了一个接口值,其中包含一个nil
值和该类型*MyErr
,因此该接口值不是nil
。解决方法
我无法理解如何正确确保
nil
在这种情况下不存在某些问题:package main type shower interface { getWater() []shower } type display struct { SubDisplay *display } func (d display) getWater() []shower { return []shower{display{},d.SubDisplay} } func main() { // SubDisplay will be initialized with null s := display{} // water := []shower{nil} water := s.getWater() for _,x := range water { if x == nil { panic("everything ok,nil found") } //first iteration display{} is not nil and will //therefore work,on the second iteration //x is nil,and getWater panics. x.getWater() } }
我发现检查该值是否实际的唯一方法
nil
是使用反射。这真的是想要的行为吗?还是在代码中看不到一些重大错误?
0 <nil> true 1 <nil> false 2 <nil> false 3 <nil> true 4 <nil> false
@H_419_35@在情况2
nil
中,返回了一个指针,但首先将其转换为接口类型(error
),因此创建了一个接口值,其中包含一个nil
值和该类型*MyErr
,因此该接口值不是nil
。解决方法
我无法理解如何正确确保
nil
在这种情况下不存在某些问题:package main type shower interface { getWater() []shower } type display struct { SubDisplay *display } func (d display) getWater() []shower { return []shower{display{},d.SubDisplay} } func main() { // SubDisplay will be initialized with null s := display{} // water := []shower{nil} water := s.getWater() for _,x := range water { if x == nil { panic("everything ok,nil found") } //first iteration display{} is not nil and will //therefore work,on the second iteration //x is nil,and getWater panics. x.getWater() } }
我发现检查该值是否实际的唯一方法
nil
是使用反射。这真的是想要的行为吗?还是在代码中看不到一些重大错误?
package main
type shower interface {
getWater() []shower
}
type display struct {
SubDisplay *display
}
func (d display) getWater() []shower {
return []shower{display{},d.SubDisplay}
}
func main() {
// SubDisplay will be initialized with null
s := display{}
// water := []shower{nil}
water := s.getWater()
for _,x := range water {
if x == nil {
panic("everything ok,nil found")
}
//first iteration display{} is not nil and will
//therefore work,on the second iteration
//x is nil,and getWater panics.
x.getWater()
}
}
输出:
在情况2nil
中,返回了一个指针,但首先将其转换为接口类型(error
),因此创建了一个接口值,其中包含一个nil
值和该类型*MyErr
,因此该接口值不是nil
。
我无法理解如何正确确保nil
在这种情况下不存在某些问题:
我发现检查该值是否实际的唯一方法nil
是使用反射。
这真的是想要的行为吗?还是在代码中看不到一些重大错误?
输出:
0 <nil> true 1 <nil> false 2 <nil> false 3 <nil> true 4 <nil> false
@H_419_35@在情况2
nil
中,返回了一个指针,但首先将其转换为接口类型(error
),因此创建了一个接口值,其中包含一个nil
值和该类型*MyErr
,因此该接口值不是nil
。解决方法
我无法理解如何正确确保
nil
在这种情况下不存在某些问题:package main type shower interface { getWater() []shower } type display struct { SubDisplay *display } func (d display) getWater() []shower { return []shower{display{},d.SubDisplay} } func main() { // SubDisplay will be initialized with null s := display{} // water := []shower{nil} water := s.getWater() for _,x := range water { if x == nil { panic("everything ok,nil found") } //first iteration display{} is not nil and will //therefore work,on the second iteration //x is nil,and getWater panics. x.getWater() } }
我发现检查该值是否实际的唯一方法
nil
是使用反射。这真的是想要的行为吗?还是在代码中看不到一些重大错误?
package main
type shower interface {
getWater() []shower
}
type display struct {
SubDisplay *display
}
func (d display) getWater() []shower {
return []shower{display{},d.SubDisplay}
}
func main() {
// SubDisplay will be initialized with null
s := display{}
// water := []shower{nil}
water := s.getWater()
for _,x := range water {
if x == nil {
panic("everything ok,nil found")
}
//first iteration display{} is not nil and will
//therefore work,on the second iteration
//x is nil,and getWater panics.
x.getWater()
}
}
在情况2nil
中,返回了一个指针,但首先将其转换为接口类型(error
),因此创建了一个接口值,其中包含一个nil
值和该类型*MyErr
,因此该接口值不是nil
。
我无法理解如何正确确保nil
在这种情况下不存在某些问题:
我发现检查该值是否实际的唯一方法nil
是使用反射。
这真的是想要的行为吗?还是在代码中看不到一些重大错误?
在情况2nil
中,返回了一个指针,但首先将其转换为接口类型(error
),因此创建了一个接口值,其中包含一个nil
值和该类型*MyErr
,因此该接口值不是nil
。