Golang中为什么不建议创建类型集合

Golang中为什么不建议创建类型集合 我们通常使用集合的数据结构,而不是创建一个值为空结构体的映射。 我认为这非常相似,并且易于使用,但经常使用时可能会非常繁琐。 因为在初始化时,我们可能会这样做:

a:=make(map[int]struct{})
a[1]=struct{}
a[2]=struct{}

或者

c:=map[int]struct{}{1:{},2:{}}

当我想要并集或交集时,没有内置函数。

我们也可以编写如下代码:

type Set[T comparable] map[T]struct{}

func union[T comparable](s1 Set[T], s2 Set[T]) Set[T] {
	ret := Set[T]{}
	for k, _ := range s1 {
		ret[k] = struct{}{}
	}
	for k, _ := range s2 {
		ret[k] = struct{}{}
	}
	return ret
}

但我认为如果我们能像下面这样使用会更优雅:

a:=make(set[int])
b:=make(set[int])
a.Union(b)

更多关于Golang中为什么不建议创建类型集合的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

因为 set 是一个无序唯一元素的集合,而 Go 语言已经将切片作为此类集合的基础类型。它们是否唯一取决于具体的使用场景。有一些第三方库可以提供你所需的功能,或者你也可以自己编写一些代码。遗憾的是,我认为它不会作为一个独立的类型被添加到语言中。因为其设计理念是提供基础组件,以便构建更复杂的功能。

更多关于Golang中为什么不建议创建类型集合的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢您的回复。我确实认为应该将其添加为标准类型,因为大多数语言都将其视为内置类型,并且开发者经常使用它。

虽然这能让Go语言对初学者更简单,但大多数开发者可能会频繁使用集合。

就像在早期版本中,我们没有maxmin函数,但在当前版本中我们可以使用它们一样。

关于这个提案,多年来已有大量讨论在此处。也许有一天它会带来一些改变,但这就是我们今天所面对的Go语言现状。目前,我们必须根据具体情况,自己为基础类型实现此类功能,或者使用已经编写好的包。我来自Python背景,有时也非常怀念set。一切皆源于提案和人们的选择。得益于泛型,我们现在有了Min和Max函数,这大大减少了实现这些基础功能所需的代码量。说实话,由于泛型的存在,集合(set)同样可以被添加进来,因为你不再需要编写大量代码。

在Go语言中确实没有内置的集合类型,但使用map[T]struct{}作为集合是标准实践。虽然你提到的语法不够优雅,但这是Go目前的最佳方案。以下是更完整的实现示例:

type Set[T comparable] map[T]struct{}

func NewSet[T comparable](values ...T) Set[T] {
    s := make(Set[T])
    s.Add(values...)
    return s
}

func (s Set[T]) Add(values ...T) {
    for _, v := range values {
        s[v] = struct{}{}
    }
}

func (s Set[T]) Contains(v T) bool {
    _, ok := s[v]
    return ok
}

func (s Set[T]) Union(other Set[T]) Set[T] {
    result := make(Set[T])
    for v := range s {
        result[v] = struct{}{}
    }
    for v := range other {
        result[v] = struct{}{}
    }
    return result
}

func (s Set[T]) Intersection(other Set[T]) Set[T] {
    result := make(Set[T])
    for v := range s {
        if _, ok := other[v]; ok {
            result[v] = struct{}{}
        }
    }
    return result
}

func (s Set[T]) Difference(other Set[T]) Set[T] {
    result := make(Set[T])
    for v := range s {
        if _, ok := other[v]; !ok {
            result[v] = struct{}{}
        }
    }
    return result
}

// 使用示例
func main() {
    s1 := NewSet(1, 2, 3)
    s2 := NewSet(2, 3, 4)
    
    union := s1.Union(s2)        // {1, 2, 3, 4}
    intersection := s1.Intersection(s2) // {2, 3}
    difference := s1.Difference(s2)     // {1}
    
    s1.Add(5, 6)
    exists := s1.Contains(3)     // true
}

虽然这需要一些样板代码,但提供了类型安全的集合操作。社区中也有一些第三方库如github.com/deckarep/golang-set提供了更完整的实现。

回到顶部