Pair/tuple data type in Go
Asked Answered
S

6

186

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.

Surprise answered 2/12, 2012 at 15:43 Comment(0)
E
85

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.

Emulsion answered 3/12, 2012 at 15:8 Comment(1)
What about github.com/golang/go/blob/… ?Hailstone
E
129

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.

Emulsion answered 2/12, 2012 at 16:6 Comment(4)
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!Farra
however, this won't work if there are multiple fields with the same typeCalvary
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.Emulsion
So the answer is "no, there's no tuple type"?Surprise
E
85

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.

Emulsion answered 3/12, 2012 at 15:8 Comment(1)
What about github.com/golang/go/blob/… ?Hailstone
F
57

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.

Farra answered 2/12, 2012 at 16:15 Comment(0)
P
34

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

Proxy answered 29/12, 2021 at 9:27 Comment(3)
It should be: First T Second ULuffa
Sorry! Old habit I guess :)! Anyway @Hav edited the snippet so it should be good now.Proxy
At present, this is the most accurate answer for the question.Step
O
2
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))
}
Oneidaoneil answered 14/4, 2023 at 6:18 Comment(0)
G
0

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

Gollin answered 31/5, 2022 at 16:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.