Тип данных пары/кортежа в Go
Выполняя окончательное упражнение Tour of Go, я решил, что мне нужна очередь (string
, int
)., Это достаточно легко:
type job struct {
url string
depth int
}
queue := make(chan job)
queue <- job{url, depth}
Но это заставило меня задуматься: есть ли встроенные типы данных пары/кортежа в Go? Существует поддержка возврата нескольких значений из функции, но AFAICT, полученные множественные кортежи, не являются первоклассными гражданами в системе типа Go. Это тот случай?
Что касается части "что вы пробовали", то очевидный синтаксис (от POV-программиста POV)
queue := make(chan (string, int))
не работает.
Ответы
Ответ 1
В Go нет типа кортежа, и вы правы, множественные значения, возвращаемые функциями, не представляют объект первого класса.
Ответ Nick показывает, как вы можете сделать что-то подобное, которое обрабатывает произвольные типы с помощью интерфейса {}. (Я мог бы использовать массив, а не структуру, чтобы сделать его индексируемой, как кортеж, но ключевой идеей является тип интерфейса {}.)
Мой другой ответ показывает, как вы можете сделать что-то подобное, что позволяет избежать создания типа с использованием анонимных структур.
Эти методы имеют некоторые свойства кортежей, но нет, они не являются кортежами.
Ответ 2
Вы можете это сделать. Он выглядит более многословным, чем кортеж, но это большое улучшение, потому что вы получаете проверку типов.
Изменить: Заменен фрагмент с полным рабочим примером, следуя предложению Ника. Ссылка на игровое поле: 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}
}
Анонимные структуры и поля отлично подходят для быстрых и грязных решений. Однако для всех, кроме самых простых случаев, вам лучше определить именованную структуру, как и вы.
Ответ 3
Вы можете сделать что-то вроде этого, если хотите
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)
}
Однако я думаю, что вы уже совершенно идиоматичны, и структура прекрасно описывает ваши данные, что является большим преимуществом по сравнению с использованием простых кортежей.