【问题标题】:Deadlock in channels communication between two packages - Golang两个包之间的通道通信死锁 - Golang
【发布时间】:2021-01-03 19:34:26
【问题描述】:

两个包之间的通道通信死锁 - Golang。

我有两个包通过两个渠道进行通信。一个是主要的,另一个是功能。当我运行它时,我会遇到死锁。

package main

import (
    functionspackage "GoEjemplos/subFolder"
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup

    ChannelSendData := make(chan functionspackage.FunctionStruct, 1)
    defer close(ChannelSendData)

    data := functionspackage.FunctionStruct{
        FieldOne: 3.56,
        FieldTwo: 23,
    }

    ChannelSendData <- data

    wg.Add(1)
    go functionspackage.FunctionExt(ChannelSendData, &wg)

    recibe := <-functionspackage.ChannelOutFunct

    fmt.Println("channelOut: ", recibe)

    close(functionspackage.ChannelOutFunct)

    wg.Wait()
}

另一个包是

package functionspackage

import "sync"

type FunctionStruct struct {
    FieldOne float64
    FieldTwo int
}

var ChannelOutFunct chan float64

func FunctionExt(RecibeChan chan FunctionStruct, wg *sync.WaitGroup) (ChannelOutFunct chan float64) {

    reciveData := <-RecibeChan

    result := reciveData.FieldOne * float64(reciveData.FieldTwo)

    ChannelOutFunct <- result

    wg.Done()

    return ChannelOutFunct
}

这是死锁。

PS C:\Go-Project\src\GoEjemplos> go run main.go
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive (nil chan)]:
main.main()
        C:/Go-Project/src/GoEjemplos/main.go:32 +0x13d

goroutine 19 [chan send (nil chan)]:
GoEjemplos/subFolder.FunctionExt(0xc0000d4000, 0xc0000a2070, 0xc0000c9f18)
        C:/Go-Project/src/GoEjemplos/subFolder/functionsPackage.go:19 +0x85
created by main.main
        C:/Go-Project/src/GoEjemplos/main.go:30 +0x11a
exit status 2
PS C:\Go-Project\src\GoEjemplos>

你能解释一下问题出在哪里吗?

谢谢!

【问题讨论】:

    标签: go package deadlock channels


    【解决方案1】:

    我让它工作了。这是代码

    package main
    
    import (
        packagefunctions "GoEjemplos/subFolder"
        "fmt"
        "sync"
    )
    
    func main() {
        var wg sync.WaitGroup
        var ChannelSendData = make(chan packagefunctions.FunctionStruct, 0)
        defer close(ChannelSendData)
        var ChanReturn = make(chan float64)
        defer close(ChanReturn)
    
        data := packagefunctions.FunctionStruct{
            FieldOne: 3.56,
            FieldTwo: 2,
        }
    
        wg.Add(1)
        go func() { ChannelSendData <- data }()
    
        wg.Add(1)
        go func() {
            ChanReturn = packagefunctions.FunctionExt(ChannelSendData, &wg)
            recibeChanReturn := <-ChanReturn
            fmt.Println("channelOut: ", recibeChanReturn)
            wg.Done()
        }()
        wg.Wait()
    }
    

    另一个包是

    package packagefunctions
    
    import (
        "fmt"
        "sync"
    )
    
    type FunctionStruct struct {
        FieldOne float64
        FieldTwo int
    }
    
    func FunctionExt(ChanIn chan FunctionStruct, wg *sync.WaitGroup) chan float64 {
        reciveData, ok := <-ChanIn
        if ok == false {
            fmt.Println("channel closed")
        }
        var result float64
        result = reciveData.FieldOne * float64(reciveData.FieldTwo)
        var ChannelReturn = make(chan float64, 1)
        defer close(ChannelReturn)
        ChannelReturn <- result
        wg.Done()
        return ChannelReturn
    }
    

    【讨论】:

      【解决方案2】:

      频道functionspackage.ChannelOutFunct 未初始化,因此它是一个零频道。写入零通道或从零通道读取将始终阻塞。

      https://dave.cheney.net/2014/03/19/channel-axioms

      【讨论】:

      • 感谢您的回复。无论如何,我需要你能帮我多一点。我了解通道未初始化并导致错误。但我不知道我应该在哪里初始化它,因为据我了解它已经在函数包包中初始化(var ChannelOutFunct chan float64)如果我删除该通道并将其初始化为main,它与函数的返回有何关系在其他包中找到?对于给您带来的不便,我深表歉意。我正在努力学习 Go 编程。
      • 未初始化,已声明,所以为nil。您可以声明并初始化它:var ChannelOutFunct = make(chan float64)。您也可以在main 中对其进行初始化。它在不同的包中在这里没有任何意义。
      猜你喜欢
      • 2019-05-10
      • 2014-11-14
      • 2019-08-30
      • 2017-10-05
      • 2011-08-24
      • 1970-01-01
      • 2019-05-29
      • 2017-07-02
      • 2017-06-24
      相关资源
      最近更新 更多