Go 中泛型结构的类型推断

问题描述 投票:0回答:1

考虑以下代码

import "fmt"

type key1 int
type key2 string
type value int

type m1 map[key1]value
type m2 map[key2]value

type A[key key1 | key2, t ~map[key]value] struct {
    m t
}

// I chose an example involving looping through a map to highlight the need of defining the map itself in the constraint.
func (a A[t, key]) foo() {
    for k, v := range a.m {
        fmt.Println(k, v)
    }
}

func main() {
    A[key1, m1]{
        m: m1{1: 1},
    }.foo() // prints: 1 1

    A[key2, m2]{
        m: m2{"one": 1},
    }.foo() // prints: one 1
}

演示

在更复杂的设置中,我需要编写一个更长的“通用表达式”,并且需要重复多次(每个方法一次)。因此,我很乐意用更短的表达来代替它。我尝试过类似的事情

type constrainKey interface {
    key1 | key2
}

type constrainMap interface {
    map[constrainKey]value
}

type A[t constrainMap] struct {
    m t
}

func (a A[constrainMap]) foo() {
    for k, v := range a.m {
        fmt.Println(k, v)
    }
}

但是编译失败。你能帮我找到一个更短/更简单的约束表达式吗?帮我找到一个可以单独表示约束的接口定义

key key1 | key2, t ~map[key]value

go generics type-inference
1个回答
0
投票

这里无法简化实例化。

只要您想要参数化键类型,就必须为其指定单独的类型参数。只要结构体定义上有两个类型参数,就必须始终实例化它们。

有一个关于将类型推断扩展到泛型类型的未决问题,但该语言尚不支持它。

类型推断确实适用于函数。因此,唯一可能的解决方法是定义一个接受泛型类型作为参数的函数:

func DoFoo[K key1 | key2, M ~map[K]value](m M) {
    A[K, M]{
        m: m,
    }.foo()
} 

然后用所需的参数调用它:

func main() {
    Foo(m1{1: 1})
    Foo(m2{"one": 1})
}

显然,您始终可以从此函数返回

A
,以防以后需要使用该结构。

func DoFoo[K key1 | key2, M ~map[K]value](m M) A[K, M] {
    a := A[K, M]{
        m: m,
    }
    a.foo()
    return a
} 

游乐场https://go.dev/play/p/tOKO8ic1hZX

© www.soinside.com 2019 - 2024. All rights reserved.