Синхронизированные каналы? - PullRequest
1 голос
/ 16 января 2012

Предположим, я анализирую какой-то ввод с помощью следующих трех методов:

func parseHeader ([]byte) []byte
func parseBody   ([]byte) []byte
func parseFooter ([]byte) []byte

Все они анализируют определенную часть одного и того же ввода и возвращают его как []byte, поэтому их можно использовать так:

i := []byte( /* the input */ )
b := new(bytes.Buffer)

b.Write(parseHeader(i))
b.Write(parseBody(i))
b.Write(parseFooter(i))

Теперь я хотел бы сделать эти 3 процесса параллельными, используя каналы. Моя идея заключалась в передаче канала этим функциям для записи в них, но как я могу убедиться, что они будут писать в канал в правильном порядке? (то есть, что тело записывается в канал после верхний и нижний колонтитулы после тело)

Ответы [ 2 ]

5 голосов
/ 16 января 2012

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

Вот минимальный пример:

package main

import "fmt"

func sendme(num int, ch chan int) {
        ch <- num // send integer 'num' down chan ch
}

func main() {
        // Create three new channels
        one := make(chan int)
        two := make(chan int)
        three := make(chan int)

        // Start each parallel invocation of "sendme" as a go routine, in any order
        go sendme(3, three)
        go sendme(1, one)
        go sendme(2, two)

        // Read from each channel in the order we wish to process the
        // data
        fmt.Println(<- one, <- two, <- three)
}
1 голос
/ 16 января 2012

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

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func deferredString(lbl string, f func() string) (rv chan string) {
    rv = make(chan string)
    go func() {
        s := f()
        fmt.Printf("Finished %s\n", lbl)
        rv <- s
    }()
    return rv
}

func do(rv string) string {
    t := rand.Intn(5)
    fmt.Printf("Sleeping for %d seconds for %s\n", t, rv)
    time.Sleep(time.Duration(t) * time.Second)
    return rv
}

func main() {
    rand.Seed(int64(time.Now().Nanosecond()))

    cha := deferredString("a", func() string { return do("a") })
    chb := deferredString("b", func() string { return do("b") })
    chc := deferredString("c", func() string { return do("c") })

    fmt.Printf("a:  %s\n", <-cha)
    fmt.Printf("b:  %s\n", <-chb)
    fmt.Printf("c:  %s\n", <-chc)
}
...