空切片(empty slice)和空值(nil value)的比较

huangapple go评论74阅读模式
英文:

Nil slice vs empty slice and nil value comparison

问题

我已经阅读了关于nil切片和空切片的一些文本。我相信我对它们之间的区别有一些基本的理解。

我对理解的总结是:var instance []Type 是一个nil切片,instance == nil 返回 true;而 instance:=[]Type{} 是一个空切片,instance != nil

然而,这个特定的例子仍然让我感到困惑。

请查看下面的链接以获取代码。我的问题是最后两个例子。
https://play.golang.org/p/udyHoOlSeP

假设我想比较两个切片,包括类型和接口匹配等。在一个接收器可以是 nil 的情况下,即使它没有被定义为按值复制;而参数是按值复制的,似乎只要参数不是无类型的,接收器就不是 nil

在最后两个例子中,接收器被识别为 nil,而参数正在被 := 处理,所以它变成了一个空切片。(但是 other == nil 也报告为假...)我该如何修复这个问题以满足以下要求?


此外,我尝试定义另一个与接口指针进行比较的接口,但失败了。编译器报错:

cannot use p (type *AnotherNullable) as type *PointerComparable in argument to AnotherNullable(nil).Equals: *PointerComparable is pointer to interface, not interface
https://play.golang.org/p/wYO1GKcBds

我该如何修复这个问题?

编辑:感谢 @zippoxer 提供的所有见解。我学到了很多。我希望新读者也能记得查看答案中 @zippoxer 的评论!

英文:

I have read some text regarding nil slice vs empty slice. I believe I have some basic understanding of the differences between them.

Summary of my understanding: var instance []Type is nil slice and instance == nil returns true; while instance:=[]Type{} is empty slice and instance != nil

However this particular instance still puzzles me.

Please look at the link below for code. My question is the last 2 cases.
https://play.golang.org/p/udyHoOlSeP

Suppose I want to compare two slices, renamed type and interface matching and all. The instance where a receiver can be nil, even though it's not defined as copy by value; while the argument is copied by value, seems to
be non-nil as long as the argument is not untyped.

In the last 2 cases, receiver has been identified as nil while argument is being processed by := so it becomes an empty slice. (But the other == nil also reports false...) How can I fix this to satisfy the following requirement?


Further, I tried to define another interface comparing to pointers of interface but failed. Compiler complains that

cannot use p (type *AnotherNullable) as type *PointerComparable in argument to AnotherNullable(nil).Equals:
*PointerComparable is pointer to interface, not interface

https://play.golang.org/p/wYO1GKcBds

How can I fix that?

EDIT: Thanks to @zippoxer for all the insights. I learned a lot. I hope new readers too, please don't forget to check out @zippoxer's comment in the answer too!

答案1

得分: 4

首先,你不需要一个指向接口的指针。接口本身就是一个指针。
参考链接:https://stackoverflow.com/questions/23148812/go-whats-the-meaning-of-interface/23148998#23148998

只需将Equals方法更改为接受PointerComparable而不是*PointerComparable。Equals将接受一个接口而不是接口的指针,但你仍然可以将指向切片/其他内容的指针传递给它。
参考链接:https://play.golang.org/p/e_Gtq2oAFA

其次,接收器Nullable不是一个接口,而你传递给Equals的参数是一个接口。这就解释了为什么Nullable接收器保持为nil,而Comparable参数不是nil,尽管它的底层切片是nil。事实上,Comparable参数是一个指向某个东西的接口,所以无论它指向什么,它都不会是nil。

以下代码解释了这个问题:

var a interface{}
fmt.Println(a == nil) // true,接口没有指向任何东西
var someNilSlice []int
fmt.Println(someNilSlice == nil) // true,只是一个空的切片
a = someNilSlice
fmt.Println(a == nil) // false,现在接口指向了某个东西
英文:

First, you don't need a pointer to an interface. An interface is already a pointer.
See https://stackoverflow.com/questions/23148812/go-whats-the-meaning-of-interface/23148998#23148998

Just change the Equals method to accept a PointerComparable instead of a *PointerComparable. Equals will accept an interface instead of a pointer to an interface, but you can still pass a pointer to a slice/whatever to it.
See https://play.golang.org/p/e_Gtq2oAFA

Second, the receiver Nullable isn't an interface, while the argument you pass to Equals is an interface. That would explain why the Nullable receiver stays nil and the Comparable argument isn't nil although it's underlying slice is. The thing is, the Comparable argument is an interface that points to something, so whatever it points to, it won't be nil.

This code explains the problem:

var a interface{}
fmt.Println(a == nil) // true, the interface doesn't point to anything
var someNilSlice []int
fmt.Println(someNilSlice == nil) // true, just some nil slice
a = someNilSlice
fmt.Println(a == nil) // false, now the interface does point to something

huangapple
  • 本文由 发表于 2015年12月16日 20:25:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/34312010.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定