所有go例程都处于休眠状态-死锁

所有go例程都处于休眠状态-死锁,go,goroutine,Go,Goroutine,我不明白为什么这段代码会出现死锁。我尝试了几种不同的方法来停止死锁(使用WorkGroup的几种不同版本)。这是我进入围棋的第一天,到目前为止,我对相当简单和直接的操作的复杂性感到非常失望。我觉得我遗漏了一些重大而明显的东西,但我在上面找到的所有文档似乎都与我认为非常基本的操作模式大不相同。所有文档都对通道使用基本类型(int、string),而不是更复杂的类型,所有文档都具有非常基本的for循环,或者它们位于功能相当复杂的编排的另一端 我想我真的在寻找一个关于goroutines的“这就是通常

我不明白为什么这段代码会出现死锁。我尝试了几种不同的方法来停止死锁(使用WorkGroup的几种不同版本)。这是我进入围棋的第一天,到目前为止,我对相当简单和直接的操作的复杂性感到非常失望。我觉得我遗漏了一些重大而明显的东西,但我在上面找到的所有文档似乎都与我认为非常基本的操作模式大不相同。所有文档都对通道使用基本类型(int、string),而不是更复杂的类型,所有文档都具有非常基本的for循环,或者它们位于功能相当复杂的编排的另一端

我想我真的在寻找一个关于goroutines的“这就是通常的做法”的中间示例

package main

import "fmt"

//import "sync"
import "time"

type Item struct {
    name string
}

type Truck struct {
    Cargo []Item
    name  string
}

func UnloadTrucks(c chan Truck) {

    for t := range c {
        fmt.Printf("%s has %d items in cargo: %s\n", t.name, len(t.Cargo), t.Cargo[0].name)
    }

}

func main() {
    trucks := make([]Truck, 2)

    ch := make(chan Truck)

    for i, _ := range trucks {

        trucks[i].name = fmt.Sprintf("Truck %d", i+1)

        fmt.Printf("Building %s\n", trucks[i].name)
    }

    for t := range trucks {
        go func(tr Truck) {

            itm := Item{}
            itm.name = "Groceries"

            fmt.Printf("Loading %s\n", tr.name)
            tr.Cargo = append(tr.Cargo, itm)
            ch <- tr

        }(trucks[t])
    }

    time.Sleep(50 * time.Millisecond)
    fmt.Println("Unloading Trucks")
    UnloadTrucks(ch)

    fmt.Println("Done")
}
主程序包
输入“fmt”
//导入“同步”
导入“时间”
类型项结构{
名称字符串
}
类型卡车结构{
货物[]项
名称字符串
}
func卸载卡车(c chan卡车){
对于t:=范围c{
fmt.Printf(“%s在货物中有%d个项目:%s\n”,t.name,len(t.cargo),t.cargo[0]。name)
}
}
func main(){
卡车:=制造([]卡车,2辆)
ch:=制造(成龙卡车)
对于i,i:=范围卡车{
卡车[i].name=fmt.Sprintf(“卡车%d”,i+1)
fmt.Printf(“建筑%s\n”,卡车[i]。名称)
}
对于t:=系列卡车{
go func(tr卡车){
itm:=项目{}
itm.name=“食品杂货”
fmt.Printf(“正在加载%s\n”,tr.name)
tr.Cargo=附加(tr.Cargo,itm)
ch您永远不会关闭“卡车”频道
ch
,因此
卸载卡车
永远不会返回

您可以在完成所有工作人员后,使用WaitGroup关闭通道:

go func() {
    wg.Wait()
    close(ch)
}()
UnloadTrucks(ch)