猿问

在控制台上不打印接收通道值

我是GoLang的学习者,正在尝试进行实验并了解Sync软件包和chan概念。


我正在运行的代码是期望在控制台上打印“接收通道值”的代码,但是该值未得到打印,它有时但并非总是打印该值。


如果我不使用chan遍历chan,那么它会打印所有通道值,但会失败,并显示错误“致命错误:所有goroutine都处于睡眠状态-死锁! ”


我尝试使用通道“完成”来同步通道读取,但是在这种情况下,它再次因相同的错误而开始失败。我还尝试了waitGroup API,您可以在我的代码中看到它(有注释),但这对我没有用。


谢谢您的帮助


源代码:


package main


import (

    "fmt"

    "sync"

)


type safeOperation struct {

    i int

    sync.Mutex

}


var wg sync.WaitGroup


func main() {

    so := new(safeOperation)

    ch := make(chan int)

    //done := make(chan bool)

    for i := 0; i < 5; i++ {

        go so.Increment(ch)

        go so.Decrement(ch)

    }


    go func() {

        //wg.Add(1)

        for c := range ch {

            fmt.Println("Receiving Channel Value: ", c)

        }

        //wg.Done()

        //done <- true

    }()

    //wg.Wait()

    //<-done

    fmt.Println("Value: ", so.GetValue())

    fmt.Println("Main method finished")

}


func (so *safeOperation) Increment(ch chan int) {

    //so.Lock()

    //defer wg.Done()

    so.i++

    ch <- so.i

    //so.Unlock()

}


func (so *safeOperation) Decrement(ch chan int) {

    //so.Lock()

    //defer wg.Done()

    so.i--

    ch <- so.i

    //so.Unlock()

}


func (so *safeOperation) GetValue() int {

    so.Lock()

    v := so.i

    so.Unlock()

    return v

}

输出: 值:1主要方法完成


温温酱
浏览 212回答 1
1回答

元芳怎么了

一个很好的使用方式WaitGroup是Add()在发送到频道之前先调用,或者使用go关键字,Done()在从频道接收后再调用。这样Add(),无论是否在通道块上发送,都可以确保始终按时调用。我已经更改了您的示例代码来做到这一点:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "sync")type safeOperation struct {&nbsp; &nbsp; i int&nbsp; &nbsp; sync.Mutex}var wg sync.WaitGroupfunc main() {&nbsp; &nbsp; so := new(safeOperation)&nbsp; &nbsp; ch := make(chan int)&nbsp; &nbsp; for i := 0; i < 5; i++ {&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go so.Increment(ch)&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go so.Decrement(ch)&nbsp; &nbsp; }&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; for c := range ch {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Receiving Channel Value: ", c)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }()&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; //<-done&nbsp; &nbsp; fmt.Println("Value: ", so.GetValue())&nbsp; &nbsp; fmt.Println("Main method finished")}func (so *safeOperation) Increment(ch chan int) {&nbsp; &nbsp; so.i++&nbsp; &nbsp; ch <- so.i}func (so *safeOperation) Decrement(ch chan int) {&nbsp; &nbsp; so.i--&nbsp; &nbsp; ch <- so.i}func (so *safeOperation) GetValue() int {&nbsp; &nbsp; so.Lock()&nbsp; &nbsp; v := so.i&nbsp; &nbsp; so.Unlock()&nbsp; &nbsp; return v}当然,您还希望safeOperation.i使用互斥锁进行保护(否则其值将是不可预测的),但这就是获得所需输出所必需的全部操作。
随时随地看视频慕课网APP

相关分类

Go
我要回答