157

在进行Tour of Go 的最后练习时,我决定需要一个 ( string, int) 对的队列。这很容易:

type job struct {
    url string
    depth int
}

queue := make(chan job)
queue <- job{url, depth}

但这让我想到:Go 中有内置的对/元组数据类型吗?支持从函数返回多个值,但是 AFAICT,产生的多个值元组不是 Go 类型系统中的一等公民。是这样吗?

至于“你尝试过什么”部分,显而易见的语法(来自 Python 程序员的 POV)

queue := make(chan (string, int))

没用。

4

4 回答 4

112

你可以这样做。它看起来比元组更冗长,但这是一个很大的改进,因为您可以进行类型检查。

编辑:按照尼克的建议,用完整的工作示例替换片段。游乐场链接:http ://play.golang.org/p/RNx_otTFpk

package main

import "fmt"

func main() {
    queue := make(chan struct {string; int})
    go sendPair(queue)
    pair := <-queue
    fmt.Println(pair.string, pair.int)
}

func sendPair(queue chan struct {string; int}) {
    queue <- struct {string; int}{"http:...", 3}
}

匿名结构和字段适用于像这样的快速和肮脏的解决方案。但是,对于除了最简单的情况之外的所有情况,您最好像您所做的那样定义一个命名结构。

于 2012-12-02T16:06:06.363 回答
77

Go 中没有元组类型,你是对的,函数返回的多个值并不代表一等对象。

尼克的回答展示了如何使用interface{}. (我可能使用数组而不是结构来使其像元组一样可索引,但关键是interface{}类型)

我的另一个答案显示了如何做类似的事情来避免使用匿名结构创建类型。

这些技术具有元组的一些属性,但不,它们不是元组。

于 2012-12-03T15:08:35.400 回答
53

如果你愿意,你可以做这样的事情

package main

import "fmt"

type Pair struct {
    a, b interface{}
}

func main() {
    p1 := Pair{"finished", 42}
    p2 := Pair{6.1, "hello"}
    fmt.Println("p1=", p1, "p2=", p2)
    fmt.Println("p1.b", p1.b)
    // But to use the values you'll need a type assertion
    s := p1.a.(string) + " now"
    fmt.Println("p1.a", s)
}

但是,我认为您已经拥有的内容是完全惯用的,并且该结构完美地描述了您的数据,这比使用普通元组具有很大的优势。

于 2012-12-02T16:15:23.960 回答
3

Go 1.18(预计 2022 年 2 月发布)将增加对泛型的支持。

这将使声明元组类型变得非常容易:

type Pair[T, U any] struct{
    T First
    U Second
}

func main() {
    queue := make(chan Pair[string, int])
}

您可以立即使用 Beta 版试用!

您还可以使用我编写的通用元组库(go-tuple)。

于 2021-12-29T09:27:50.030 回答