Взаимоблокировка в каналах связи между двумя пакетами — Golang

#go #package #deadlock #channels

#Вперед #пакет #взаимоблокировка #Каналы

Вопрос:

Взаимоблокировка в каналах связи между двумя пакетами — 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, amp;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-ProjectsrcGoEjemplos> 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-ProjectsrcGoEjemplos>
  

Не могли бы вы объяснить мне, в чем проблема?

Спасибо!

Ответ №1:

Канал functionspackage.ChannelOutFunct не инициализирован, поэтому он является нулевым каналом. Запись в нулевой канал или чтение из нулевого канала всегда будут блокироваться.

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

Комментарии:

1. Я ценю ваш ответ. В любом случае, мне нужно, если вы можете помочь мне немного больше. Я понимаю, что канал не инициализирован, и это вызывает ошибку. Но я не знаю, где я должен его инициализировать, потому что, насколько я понимаю, он уже был инициализирован в пакете functionspackage (var ChannelOutFunct chan float64) Если я удалю этот канал и инициализирую его в main, как это будет связано с возвратом функции, найденной в другом пакете? Приношу свои извинения за доставленные неудобства. Я пытаюсь научиться программированию на Go.

2. Он не инициализирован, он объявлен, поэтому он равен нулю. Вы можете объявить и инициализировать его: var ChannelOutFunct = make(chan float64) . Вы также можете инициализировать его main . Это находится в другом пакете, здесь не имеет никакого значения.

Ответ №2:

Я заставил это работать. Это код

 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, amp;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
}