Тип данных пара / кортеж в Go

118

Выполняя последнее упражнение Tour of Go , я решил, что мне нужна очередь из пар ( string, int). Это достаточно просто:

type job struct {
    url string
    depth int
}

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

Но это заставило меня задуматься: есть ли в Go встроенные типы данных пара / кортеж? Существует поддержка возврата нескольких значений из функции, но AFAICT, созданные кортежи с несколькими значениями не являются первоклассными гражданами в системе типов Go. Так ли это?

Что касается части «что вы пробовали», очевидный синтаксис (из точки зрения программиста Python)

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

не сработало.

Фред Фу
источник

Ответы:

57

В Go нет кортежного типа, и вы правы, множественные значения, возвращаемые функциями, не представляют собой первоклассный объект.

Ответ Ника показывает, как вы можете сделать что-то подобное, которое обрабатывает произвольные типы, используя interface{}. (Я мог бы использовать массив, а не структуру, чтобы сделать его индексируемым, как кортеж, но ключевой идеей является interface{}тип)

Другой мой ответ показывает, как можно сделать что-то подобное, избегая создания типа с использованием анонимных структур.

У этих методов есть некоторые свойства кортежей, но нет, они не кортежи.

Соня
источник
91

Ты можешь сделать это. Он выглядит более многословным, чем кортеж, но это большое улучшение, потому что вы получаете проверку типов.

Изменить: заменен фрагмент полным рабочим примером, следуя предложению Ника. Ссылка на игровую площадку: 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}
}

Анонимные структуры и поля подходят для быстрых и грязных решений, подобных этому. Однако для всех, кроме простейших случаев, вам лучше определить именованную структуру, как и вы.

Соня
источник
9
Вам, вероятно, следует описать, как получить значения из анонимных членов структуры, потому что я не думаю, что это очевидно для новичка!
Ник Крейг-Вуд,
9
однако это не сработает, если есть несколько полей одного типа
newacct
1
Вы можете иметь именованные поля в анонимной структуре, вам просто нужно убедиться, что поля названы одинаково в каждом месте, где появляется определение анонимной структуры (три раза в этом примере). Анонимные поля проще, если вам это сойдет с рук. .
Соня
5
Итак, ответ - «нет, типа кортежа нет»?
Фред Фу,
37

Вы могли бы сделать что-то подобное, если бы захотели

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

Однако я думаю, что то, что у вас уже есть, совершенно идиоматично, и структура идеально описывает ваши данные, что является большим преимуществом по сравнению с использованием простых кортежей.

Ник Крейг-Вуд
источник