go语言多并发打印,怎么样能正确打印出结果

代码段一,查询出产品 1767,打印出产品 1767

    //查询产品列表
    GetProductLst()
    for _, pproductItem := range productLst.ProductItems {
        fmt.Printf("产品编码 %v , 规格编号%v ,中文名称%v, 英文名称%v \n",
            pproductItem.GoodsCode, pproductItem.SpecNo, pproductItem.GoodsCName,
            pproductItem.GoodsEName)
    }

代码段二
查询出1767,但每次打印出来结果不一样,有时打印1509条,有时打印1390条 , 有漏掉。
我的需求,查询 出来,用多线程打印,打印顺序可以不同,但条数不能漏掉,有没有什么办法 ?


func printProduct(pproductItem ProductItem) {
    fmt.Printf("产品编码 %v , 规格编号%v ,中文名称%v, 英文名称%v \n", pproductItem.GoodsCode, pproductItem.SpecNo, pproductItem.GoodsCName,
        pproductItem.GoodsEName)
}

func main() {
    //查询产品列表
    GetProductLst()
    for _, pproductItem := range productLst.ProductItems {
           go printProduct(pproductItem)
    }
    //暂停主线程
    runtime.Gosched()
}

当你使用 Go 的多线程并发来打印输出时,可能会发现输出的结果不正确,有些行会漏掉或者顺序发生改变。这是因为 Go 的多线程并发执行是没有任何保证的,也就是说,你无法保证线程的执行顺序或者完整性。

有几种方法可以解决这个问题:

  • 使用 sync 包的互斥锁(mutex)来保证并发访问的安全性。你可以在打印函数(printProduct)中使用互斥锁来保证同一时刻只有一个线程在执行打印操作,从而保证输出结果的正确性。
  • 使用 channel 来进行线程同步。你可以创建一个通道,在每个线程执行完成后向通道中写入数据,然后在主线程中读取通道中的数据,来保证线程的执行顺序和完整性。
  • 使用 sync 包的 WaitGroup 来进行线程同步。你可以在主线程中创建一个 WaitGroup,并在每个线程启动前将 WaitGroup 的计数加 1,在线程执行完成后将计数减 1。然后在主线程中调用 WaitGroup 的 Wait 方法等待所有线程完成,从而保证线程的执行顺序和完整性。

使用互斥锁(mutex)的代码示例:

import (
    "fmt"
    "sync"
)

var mu sync.Mutex

func printProduct(pproductItem ProductItem) {
    mu.Lock()
    defer mu.Unlock()
    fmt.Printf("产品编码 %v , 规格编号%v ,中文名称%v, 英文名称%v \n", pproductItem.GoodsCode, pproductItem.SpecNo, pproductItem.GoodsCName,
        pproductItem.GoodsEName)
}

func main() {
    // 查询产品列表
    GetProductLst()
    for _, pproductItem := range productLst.ProductItems {
        go printProduct(pproductItem)
    }
}

使用通道(channel)的代码示例:

import (
    "fmt"
)

func printProduct(pproductItem ProductItem, ch chan bool) {
    fmt.Printf("产品编码 %v , 规格编号%v ,中文名称%v, 英文名称%v \n", pproductItem.GoodsCode, pproductItem.SpecNo, pproductItem.GoodsCName,
        pproductItem.GoodsEName)
    ch <- true
}

func main() {
    ch := make(chan bool)
    // 查询产品列表
    GetProductLst()
    for _, pproductItem := range productLst.ProductItems {
        go printProduct(pproductItem, ch)
    }
    for range productLst.ProductItems {
        <-ch
    }
}