首页 文章

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

提问于
浏览
1

我是GoLang的学习者,正试图尝试和学习Sync包和chan概念 .

Follwoing是我正在运行的代码,并且希望在控制台上打印 Receiving Channel Value ,但是值不会被打印,它有时会打印值但不总是 .

如果我通过chan调整范围而不将其放入go例程中,那么它将打印所有通道值,但失败并显示错误“ fatal error: all goroutines are asleep - deadlock!

我尝试使用通道“done”同步通道读取,但在这种情况下,它再次开始失败并出现相同的错误 . 我也尝试了waitGroup API,你可以在我的代码中看到(评论),但这对我也没有用 .

谢谢您的帮助

Source Code:

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
}

Output: 值:1主要方法已完成

1 回答

  • 2

    使用 WaitGroup 的一个好模式是在发送到 Channels 或使用 go 关键字之前调用 Add() ,并在从 Channels 接收后调用 Done() . 这样,无论是否发送通道块,您都可以确保 Add() 始终被称为导通时间 .

    我已经更改了您的示例代码来执行此操作:

    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)
        for i := 0; i < 5; i++ {
            wg.Add(1)
            go so.Increment(ch)
            wg.Add(1)
            go so.Decrement(ch)
        }
    
        go func() {
            for c := range ch {
                fmt.Println("Receiving Channel Value: ", c)
                wg.Done()
            }
        }()
        wg.Wait()
        //<-done
        fmt.Println("Value: ", so.GetValue())
        fmt.Println("Main method finished")
    }
    
    func (so *safeOperation) Increment(ch chan int) {
        so.i++
        ch <- so.i
    }
    
    func (so *safeOperation) Decrement(ch chan int) {
        so.i--
        ch <- so.i
    }
    
    func (so *safeOperation) GetValue() int {
        so.Lock()
        v := so.i
        so.Unlock()
        return v
    }
    

    Go playground link

    当然,您还希望使用互斥锁保护 safeOperation.i (或者它的值将是不可预测的),但这是获得所需输出所需的全部内容 .

相关问题