Go中的配对/元组数据类型

huangapple go评论90阅读模式
英文:

Pair/tuple data type in Go

问题

我需要一个(string, int)对的队列。这很容易:

type job struct {
    url string
    depth int
}

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

Go语言中有内置的对/元组数据类型吗?虽然函数可以返回多个值,但据我所知,Go语言中产生的多值元组不是一等公民。是这样吗?

至于“你尝试了什么”的部分,显而易见的语法(从Python程序员的角度来看)

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

没有起作用。

英文:

I need a queue of (string, int) pairs. That's easy enough:

type job struct {
    url string
    depth int
}

queue := make(chan job)
queue &lt;- job{url, depth}

are there built-in pair/tuple data types in Go? There is support for returning multiple values from a function, but AFAICT, the multiple value tuples produced are not first-class citizens in Go's type system. Is that the case?

As for the "what have you tried" part, the obvious syntax (from a Python programmer's POV)

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

didn't work.

答案1

得分: 124

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

编辑:根据Nick的建议,用完整的工作示例替换了代码片段。Playground链接: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}
}

匿名结构体和字段对于像这样的快速而简单的解决方案是可以的。但对于除了最简单的情况之外,最好还是像你之前做的那样定义一个命名结构体。

英文:

You can do this. It looks more wordy than a tuple, but it's a big improvement because you get type checking.

Edit: Replaced snippet with complete working example, following Nick's suggestion. Playground link: http://play.golang.org/p/RNx_otTFpk

package main

import &quot;fmt&quot;

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

func sendPair(queue chan struct {string; int}) {
	queue &lt;- struct {string; int}{&quot;http:...&quot;, 3}
}

Anonymous structs and fields are fine for quick and dirty solutions like this. For all but the simplest cases though, you'd do better to define a named struct just like you did.

答案2

得分: 83

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

Nick的回答展示了如何使用interface{}处理任意类型的类似操作。(我可能会使用数组而不是结构体,以使其像元组一样可索引,但关键思想是interface{}类型)

我的另一个回答展示了如何使用匿名结构体来避免创建类型的类似操作。

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

英文:

There is no tuple type in Go, and you are correct, the multiple values returned by functions do not represent a first-class object.

Nick's answer shows how you can do something similar that handles arbitrary types using interface{}. (I might have used an array rather than a struct to make it indexable like a tuple, but the key idea is the interface{} type)

My other answer shows how you can do something similar that avoids creating a type using anonymous structs.

These techniques have some properties of tuples, but no, they are not tuples.

答案3

得分: 57

你可以像这样做,如果你想的话

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)
    // 但是要使用这些值,你需要进行类型断言
    s := p1.a.(string) + " now"
    fmt.Println("p1.a", s)
}

然而,我认为你已经拥有的代码是完全符合惯用方式的,结构体完美地描述了你的数据,这是使用普通元组所不具备的一个重要优势。

英文:

You could do something like this if you wanted

package main

import &quot;fmt&quot;

type Pair struct {
	a, b interface{}
}

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

However I think what you have already is perfectly idiomatic and the struct describes your data perfectly which is a big advantage over using plain tuples.

答案4

得分: 28

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

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

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

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

您现在可以尝试使用beta版本!

您还可以使用像我写的一个泛型元组库(go-tuple)来实现。

英文:

Go 1.18 (estimated to be released February 2022) will add support for generics.

This will make it very easy to declare tuple types:

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

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

You can try it with the beta right now!

You can also use a library for generic tuples like the one I wrote (go-tuple).

答案5

得分: 1

在Go语言中没有内置的元组/对。我和你一样遇到了同样的问题,所以我创建了这个简单的包,这样我就不需要在每个项目中重新发明轮子了:

Go Pair package

英文:

There are no built-in tuples/pairs in Go. I had the exact same issue with you, so I created this simple package, so I don't need to reinvent the wheel in my every project:

Go Pair package

答案6

得分: 0

type Pair struct {

values [2]interface{}

}

func MakePair(k, v interface{}) Pair {

return Pair{values:[2]interface{}{k, v}}

}

func (p Pair) Get(i int) interface{} {

return p.values[i]

}

func main() {

p := MakePair("Hello", false)

fmt.Println(p.Get(0), " ", p.Get(1))

}

英文:

type Pair struct {

values [2]interface{}

}

func MakePair(k, v interface{}) Pair {

return Pair{values:[2]interface{}{k, v}}

}

func (p Pair) Get(i int) interface{} {

return p.values[i]

}

func main() {

p := MakePair(&quot;Hello&quot;, false)

fmt.Println(p.Get(0), &quot; &quot;, p.Get(1))

}

huangapple
  • 本文由 发表于 2012年12月2日 23:43:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/13670818.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定