Синхронизированные каналы?

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

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 процесса параллельными с помощью каналов. Моя идея состояла в том, чтобы передать канал этим функциям для записи, но как я могу убедиться, что они будут писать в канал в правильном порядке? (т. е. что тело записывается в канал < em>после заголовка и нижнего колонтитула после тела)


person thwd    schedule 15.01.2012    source источник


Ответы (2)


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

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

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)
}
person snim2    schedule 15.01.2012
comment
Не могли бы вы привести пример того, как я могу сделать это, используя 3 канала, пожалуйста? =) было бы здорово. - person thwd; 16.01.2012
comment
Окей, сделано. Понятно, что можно немного поправить. Например, вы можете захотеть сохранить каналы в массиве. - person snim2; 16.01.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)
}
person Dustin    schedule 15.01.2012
comment
Вау, круто! большое спасибо. Я проанализирую это более подробно. - person thwd; 16.01.2012