您的代码中存在多个错误。最严重的是,由于您要将
visited切片的每个特定元素与的 所有
元素进行比较
unique,因此如果
unique包含至少一个不同的元素,最终将附加它。而且,如果由于
unique内部
for循环不会“中断”
而有更多不同的元素,您将最终多次追加它。这是不是你想要的,你要追加相等于元素 没有 的
unique。
还要注意,
struct如果Go中的每个字段都是可比较的,则a
in可比较。由于您的
visit结构仅包含2个
int字段,因此具有可比性,因此您可以
visit简单地将type的值与
==运算符进行比较,而不必太丑陋
reflect.DeepEqual()。请参见规格:比较运算符:
如果结构的所有字段都是可比较的,则它们的值是可比较的。如果两个结构值对应的非空白字段相等,则它们相等。
这是适用您逻辑的简化正确版本:
visited := []visit{ visit{1, 100}, visit{2, 2}, visit{1, 100}, visit{1, 1},}var unique []visitfor _, v := range visited { skip := false for _, u := range unique { if v == u { skip = true break } } if !skip { unique = append(unique, v) }}fmt.Println(unique)输出(在Go Playground上尝试):
[{1 100} {2 2} {1 1}]另类
确实,Go没有内置的集合类型,但是您可以
map[visit]bool轻松地将其用作集合。这样,它变得非常简单!请注意,
visit由于它具有可比性,因此可以用作地图中的键(请参见上文)。
visited := []visit{ visit{1, 100}, visit{2, 2}, visit{1, 100}, visit{1, 1},}unique := map[visit]bool{}for _, v := range visited { unique[v] = true}fmt.Println(unique)输出(在Go Playground上尝试):
map[{2 2}:true {1 1}:true {1 100}:true]唯一的“列表”是地图中键的列表。
如果要将唯一
visit值用作切片,请参见以下变体:
var unique []visitm := map[visit]bool{}for _, v := range visited { if !m[v] { m[v] = true unique = append(unique, v) }}fmt.Println(unique)输出(如预期的那样,在Go Playground上尝试):
[{1 100} {2 2} {1 1}]请注意,此索引表达式:
m[v]计算
true是否
v在地图中(作为键,
true是我们存储在地图中的值)。如果
v还没有在地图上,
m[v]得出这是值类型的零值
false的类型
bool,正确地告诉该值
v还没有在地图上。请参见规格:索引表达式:
对于地图类型
M:…如果地图
nil包含或不包含此类条目,a[x]则是的值类型的零值M



