Ghép nối / kiểu dữ liệu tuple trong Go


118

Trong khi thực hiện bài tập cuối cùng của Tour of Go , tôi quyết định rằng tôi cần một hàng đợi gồm ( string, int) các cặp. Điều đó đủ dễ dàng:

type job struct {
    url string
    depth int
}

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

Nhưng điều này khiến tôi phải suy nghĩ: có kiểu dữ liệu cặp / tuple được tích hợp sẵn trong Go không? Có hỗ trợ trả về nhiều giá trị từ một hàm, nhưng AFAICT, các bộ giá trị được tạo ra không phải là công dân hạng nhất trong hệ thống loại của cờ vây. Đó là trường hợp?

Đối với phần "bạn đã thử những gì", cú pháp rõ ràng (từ POV của lập trình viên Python)

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

không hoạt động.

Câu trả lời:


57

Không có loại bộ giá trị nào trong Go và bạn nói đúng, nhiều giá trị được trả về bởi các hàm không đại diện cho một đối tượng hạng nhất.

Câu trả lời của Nick cho thấy cách bạn có thể làm điều gì đó tương tự để xử lý các loại tùy ý bằng cách sử dụng interface{}. (Tôi có thể đã sử dụng một mảng thay vì một cấu trúc để làm cho nó có thể lập chỉ mục như một bộ tuple, nhưng ý tưởng chính là interface{}kiểu)

Câu trả lời khác của tôi cho thấy cách bạn có thể làm điều gì đó tương tự mà tránh tạo một loại bằng cách sử dụng cấu trúc ẩn danh.

Những kỹ thuật này có một số thuộc tính của bộ giá trị, nhưng không, chúng không phải là bộ giá trị.


91

Bạn có thể làm được việc này. Nó trông có vẻ dài dòng hơn một bộ tuple, nhưng đó là một cải tiến lớn vì bạn được kiểm tra kiểu.

Chỉnh sửa: Đoạn mã được thay thế với ví dụ hoạt động hoàn chỉnh, theo đề xuất của Nick. Liên kết sân chơi: 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}
}

Các cấu trúc và trường ẩn danh phù hợp với các giải pháp nhanh chóng và bẩn thỉu như thế này. Đối với tất cả, trừ những trường hợp đơn giản nhất, bạn nên xác định cấu trúc được đặt tên giống như cách bạn đã làm.


9
Bạn có thể nên mô tả cách lấy các giá trị ra khỏi các thành viên cấu trúc ẩn danh vì tôi không nghĩ điều đó là rõ ràng đối với người mới bắt đầu!
Nick Craig-Wood

9
Tuy nhiên, điều này sẽ không làm việc nếu có nhiều lĩnh vực với cùng loại
newacct

1
Bạn có thể có các trường được đặt tên trong một cấu trúc ẩn danh, bạn chỉ cần đảm bảo rằng các trường được đặt tên giống nhau ở mỗi vị trí mà định nghĩa cấu trúc ẩn danh xuất hiện (ba lần trong ví dụ này.) Các trường ẩn danh dễ dàng hơn nếu bạn có thể xử lý nó .
Sonia

5
Vậy câu trả lời là "không, không có loại tuple"?
Fred Foo

37

Bạn có thể làm điều gì đó như thế này nếu bạn muốn

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

Tuy nhiên, tôi nghĩ rằng những gì bạn đã có là hoàn toàn thành ngữ và cấu trúc mô tả dữ liệu của bạn một cách hoàn hảo, đó là một lợi thế lớn so với việc sử dụng các bộ giá trị đơn giản.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.