假设我正在使用以下三种方法解析某种输入:
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>在之后标题和页脚在主体之后)
答案 0 :(得分:5)
基本上你不能,至少不能没有添加额外的消息层来做额外的握手。更好的做法是使用三个独立的通道,并按照您希望接收它们的顺序从它们读取,这样您就不必担心发送过程的写入顺序。
这是一个最小的例子:
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 :(得分:1)
这是一个非常有用的例子供你玩。我在这里有额外的东西来记录序列,这样你就可以看到事情可以按顺序完成,但仍然会尽快显示,但不会早于上一次完成。
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)
}