200

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

type job struct {
    url string
    depth int
}

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

are there built-in pair/tuple data types in Go? There is support for returning multiple values from a function, but as far as I can tell, 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.

6 Answers 6

139

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 "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}
}

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.

Sign up to request clarification or add additional context in comments.

5 Comments

You should probably describe how to get the values out of the anonymous struct members because I don't think it is obvious to a beginner!
however, this won't work if there are multiple fields with the same type
You can have named fields in an anonymous struct, you just have to make sure that the fields are named the same way each place the anonymous struct definition appears (three times in this example.) Anonymous fields are easier if you can get away with it.
So the answer is "no, there's no tuple type"?
"it's a big improvement because you get type checking" is misleading because type checking tuples is perfectly possible (just not in Go).
88

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.

1 Comment

58

You could do something like this if you wanted

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)
}

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.

Comments

41

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).

3 Comments

It should be: First T Second U
Sorry! Old habit I guess :)! Anyway @Hav edited the snippet so it should be good now.
At present, this is the most accurate answer for the question.
3
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))
}

Comments

-1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.