Go的新手。我正在尝试编写一个“装配线”,其中多个函数像工作者一样工作,并将一些数据结构相互传递,每个函数都对数据结构做了一些事情。
type orderStruct struct {
orderNum,capacity int
orderCode uint64
box [9]int
}
func position0(in chan orderStruct){
order := <-in
if((order.orderCode<<63)>>63 == 1){
order.box[order.capacity] = 1
order.capacity += 1
}
fmt.Println(" filling box {", order.orderNum, order.orderCode, order.box, order.capacity, "} at position 0")
}
func startOrder(in chan orderStruct){
order := <-in
fmt.Printf("\nStart an empty box for customer order number %d , request number %d\n", order.orderNum, order.orderCode)
fmt.Println(" starting box {", order.orderNum, order.orderCode, order.box, order.capacity, "}")
d := make(chan orderStruct,1)
go position0(d)
d <- order
}
func main() {
var orders [10]orderStruct
numOrders := len(os.Args)-1
var x int
for i := 0; i < numOrders; i++{
x, _ = strconv.Atoi(os.Args[i+1])
orders[i].orderCode = uint64(x)
orders[i].orderNum = i+1
orders[i].capacity = 0
for j := 0; j < 9; j++{
orders[i].box[j] = 0
}
c := make(chan orderStruct)
go startOrder(c)
c <- orders[i]
}
}
所以基本上我遇到的问题是startOrder()中的print语句执行正常,但是当我尝试将struct传递给position0()时,没有打印任何内容。我误解了渠道是如何运作的吗?
答案 0 :(得分:1)
我试图重写您写的内容以正常工作。你可以run it on the playground
主要区别是
wg.Add(1); go startOrders(c, wg)
代码)这是代码
package main
import (
"fmt"
"sync"
)
type orderStruct struct {
orderNum, capacity int
orderCode uint64
box [9]int
}
func position0s(in chan orderStruct, wg *sync.WaitGroup) {
defer wg.Done()
for order := range in {
if (order.orderCode<<63)>>63 == 1 {
order.box[order.capacity] = 1
order.capacity += 1
}
fmt.Println(" filling box {", order.orderNum, order.orderCode, order.box, order.capacity, "} at position 0")
}
}
func startOrders(in chan orderStruct, wg *sync.WaitGroup) {
defer wg.Done()
d := make(chan orderStruct)
wg.Add(1)
go position0s(d, wg)
for order := range in {
fmt.Printf("\nStart an empty box for customer order number %d , request number %d\n", order.orderNum, order.orderCode)
fmt.Println(" starting box {", order.orderNum, order.orderCode, order.box, order.capacity, "}")
d <- order
}
close(d)
}
func main() {
var orders [10]orderStruct
numOrders := 4
var x int = 10
wg := new(sync.WaitGroup)
c := make(chan orderStruct)
wg.Add(1)
go startOrders(c, wg)
for i := 0; i < numOrders; i++ {
orders[i].orderCode = uint64(x)
orders[i].orderNum = i + 1
orders[i].capacity = 0
for j := 0; j < 9; j++ {
orders[i].box[j] = 0
}
c <- orders[i]
}
close(c)
wg.Wait()
}
答案 1 :(得分:1)
在Go中学习并发编程时,管道是一个很好的起点。 Nick Craig-Wood的回答为这一具体挑战提供了有效的解决方案。
在Go中有许多其他方法可以使用并发。从广义上讲,根据被视为并发的内容划分了三个类别:
功能分解 - 创建多个功能的管道是一个很好的入门方式 - 这是您的问题的主题。它很容易思考,而且效率很高。但是,如果它进展到真正的并行硬件,那么很难平衡负载。一切都以最慢管道阶段的速度进行。
几何分解 - 将数据划分为可以独立处理(或没有太多通信)的单独区域。基于网格的系统广泛用于科学高性能计算的某些领域,例如天气预报。
农业 - 确定如何将要完成的工作切割成(大量)任务,并将这些任务分配给工人&#39;一个接一个,直到所有的完成。通常,远的任务数量超过了工人数量。此类别包括所有所谓的“令人尴尬的并行”。问题(令人尴尬,因为如果你没有让你的高性能系统提供线性加速,你看起来有点愚蠢)。
我可以添加上述几种混合动力车的第四类。
有很多关于此的文献,包括很多来自80年代和90年代奥卡姆编程的时代。 Go和Occam都使用CSP消息传递,因此问题类似。我会挑出有用的书Practical Parallel Processing: An introduction to problem solving in parallel(Chalmers and Tidmus 1996)。