如何创建一个通用结构体?

5

我该如何构建一个通用结构体呢?

我尝试了:

type SafeSet[type T] struct {
    Values map[T]bool
}

我想能够做例如:

SafeSet{ Values: make(map[net.Conn]bool) }
SafeSet{ Values: make(map[string]  bool) }
SafeSet{ Values: make(map[int]     bool) }

2
现在,使用 Go 1.17 及更早版本是不行的。等到明年,当泛型被添加到 Go 1.18 时再试一下。 - mkopriva
@mkopriva你建议做什么呢?例如为每种类型复制SafeSet吗? - Sebastian Nielsen
类型 SafeSet map[interface{}]interface{}; x := make(SafeSet)。 - colm.anseo
@SebastianNielsen 是的,如果那正是我需要的,那就是我会做的。标准库中有类似的示例,例如 database/sql 中的 NullXxx 类型。 - mkopriva
1
https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#status - mkopriva
1个回答

2

您无法在当前的 Go 版本 1.17 中完成此操作。不幸的是,没有其他可以说的了。


在语言中添加泛型后,可能会在Go 1.18(2022年初)中实现。根据当前已接受的提案,这种参数化类型的语法将是:
type SafeSet[T comparable] struct {
    Values map[T]bool
}

特别地:

  • 类型约束在类型名称T之后
  • 如果您想将T用作映射键,则必须使用内置的约束comparable,因为映射键必须是可比较的,即支持==运算符。

然后,您必须使用实际类型参数实例化参数化类型:

示例:

要使用通用类型,您必须提供类型参数。这称为实例化。类型参数像往常一样出现在方括号中。当我们通过为类型参数提供类型参数来实例化类型时,在类型定义中使用类型参数的每个使用都将替换为相应的类型参数。

    s0 := SafeSet[net.Conn]{Values: make(map[net.Conn]bool)}
    s1 := SafeSet[string]{Values: make(map[string]bool)}
    s2 := SafeSet[int]{Values: make(map[int]bool)}

由于实例化 SafeSet 字面量有些冗长,您可以使用通用的构造函数:

func NewSafeSet[T comparable]() SafeSet[T] {
    return SafeSet[T]{Values: make(map[T]bool)}
}

显然,语法是相同的,只是在这种情况下,您需要明确地使用类型参数实例化函数:
    s3 := NewSafeSet[uint64]()
    s3.Values[200] = true

Gotip 游乐场: https://gotipplay.golang.org/p/Qyd6zTLdkRn


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接