为了账号安全,请及时绑定邮箱和手机立即绑定

go 支持多类型吗?(泛型类型)

go 支持多类型吗?(泛型类型)

Go
回首忆惘然 2022-05-23 16:49:51
type MyNumber interface {    float32, float64, uint, int // this is not supported}func PrintNumber(n MyNumber) {    switch n.(type) {    case float32, float64, uint, int:        fmt.Printf("%v\n", n)    default:        panic("PrintNumber only supports types float32, float64, uint, int")    }}在go中,可以定义一个空白接口,基本上允许任何类型var v interface{}v = "string"v = 0.1有没有办法将允许的类型减少到特定的类型列表?就像是type MyNumber float32, float64, uint, int或者type MyNumber interface {    float32, float64, uint, int}这样我就可以让编译器检查函数是否支持该类型。
查看完整描述

3 回答

?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

有没有办法将允许的类型减少到 [空接口] 的特定类型列表?

在编译时,没有。

但是,您可以选择在运行时使用限制。当有其他选择时,应该避免这种情况,因为它不能提供足够的安全性。

这是在标准库中的许多地方完成的,例如 json marshaler,它需要一个指针作为目标。


查看完整回答
反对 回复 2022-05-23
?
ITMISS

TA贡献1871条经验 获得超8个赞

您不能在编译时以您想要的方式强制使用一组具体类型。


您可以做的是使用接口。列出您期望从实现中获得的接口中的方法。那么具体的运行时类型是什么就无关紧要了。您仅通过接口与值交互,这在编译时保证它是由传递的值实现的。


例如,如果您希望该值提供一个int32值,请使用此接口:


type HasInt32 interface {

    Int32() int32

}


func f(i HasInt32) {

    fmt.Println("int32 value:", i.Int32())

}

int32传递的值是否具有或float64作为其基础类型,或者它是任何其他复杂类型都无关紧要。你需要一个int32,这就是你得到的。实现者负责如何产生该值。


例如:


type MyInt32 int32


func (m MyInt32) Int32() int32 { return int32(m) }


type MyStruct struct {

    i int64

}


func (m MyStruct) Int32() int32 { return int32(m.i) }

测试它:


var m MyInt32 = 1

f(m)


var s MyStruct = MyStruct{i: 2}

f(s)

哪些输出(在Go Playground上尝试):


int32 value: 1

int32 value: 2


查看完整回答
反对 回复 2022-05-23
?
30秒到达战场

TA贡献1828条经验 获得超6个赞

有没有办法将允许的类型减少到特定的类型列表?


是的,从 Go 1.18 开始,使用带有类型元素的接口。但是这样的接口只能作为类型参数的约束。在规范的草案版本中,接口类型下提到了这一点:


包含非接口类型、~T 形式的术语或联合的接口只能用作类型约束,或用作用作约束的其他接口的元素。它们不能是值或变量的类型,也不能是其他非接口类型的组件。


简而言之,在接口中,除了方法签名和其他嵌入式接口之外,您现在可以添加类型元素。这定义了一个类型约束,即“相应类型参数的允许类型参数集”。


尤其:


接口约束可以指定一个或多个类型元素。它将类型参数限制为指定的类型。您可以将多个类型元素指定为联合(更多信息:Go Generics - Unions)

type MyNumber interface {

    float32 | float64 | uint | int

}

您可以使用标记~来指定近似元素,即基础类型为的所有类型的集合T(更多信息:Go 中新标记〜的含义是什么(近似元素)?)。这些也可以是工会的一部分。

type MyNumber interface {

    ~float32 | ~float64 | ~uint | ~int

}

您仍然可以在这样的接口中指定方法签名。它将类型参数限制为也实现接口的那些类型的集合:

// set of types with underlying int that also implement `String() string`

type MyNumber interface {

    ~int

    String() string

}

作为上述推论,如果接口指定了非近似的预声明类型和方法,则没有类型会满足接口(因为您不能在预声明类型上声明方法)

// empty type set

type MyNumber interface {

    int

    String() string

}

如前所述,您仅将其用作类型参数约束,您将无法在类型切换、声明变量等中使用它:


func foo[T MyNumber](v T) {

    // ...

}


查看完整回答
反对 回复 2022-05-23
  • 3 回答
  • 0 关注
  • 177 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信