Golang中缓冲通道的问题探讨

Golang中缓冲通道的问题探讨 我不明白为什么缓冲通道只返回一个项目。 Playground: playground

package main

import ( “fmt” “sync” )

func Func1(wg *sync.WaitGroup, c chan string) { c <- “one1” c <- “one2” wg.Done() }

func Func2(wg *sync.WaitGroup, c chan string) { c <- “two1” c <- “two2” c <- “two3” wg.Done() }

func main() { var wg sync.WaitGroup var results []string = make([]string, 20)

c1 := make(chan string, 10) c2 := make(chan string, 10) wg.Add(2) go Func1(&wg, c1) go Func2(&wg, c2)

wg.Wait() close(c1) close(c2)

results = append(results[:], <-c1)

results = append(results[:], <-c2)

fmt.Printf(“size=%d, cap=%d, type=%T v=%v\n”, len(results), cap(results), results, results) for p, pv := range results { fmt.Println(p, pv) } }


更多关于Golang中缓冲通道的问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

谢谢Jacob,这招奏效了!

更多关于Golang中缓冲通道的问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你只在每次追加时从它读取一次。尝试:

for v := range c1 {
  results = append(results, v)
}

这是一个典型的缓冲通道使用误解。问题在于你只从每个通道读取了一次,但每个通道中都存有多个值。

让我修正你的代码:

package main

import (
	"fmt"
	"sync"
)

func Func1(wg *sync.WaitGroup, c chan string) {
	c <- "one1"
	c <- "one2"
	wg.Done()
}

func Func2(wg *sync.WaitGroup, c chan string) {
	c <- "two1"
	c <- "two2"
	c <- "two3"
	wg.Done()
}

func main() {
	var wg sync.WaitGroup
	var results []string

	c1 := make(chan string, 10)
	c2 := make(chan string, 10)
	
	wg.Add(2)
	go Func1(&wg, c1)
	go Func2(&wg, c2)

	wg.Wait()
	close(c1)
	close(c2)

	// 正确读取所有值的方法
	for v := range c1 {
		results = append(results, v)
	}
	
	for v := range c2 {
		results = append(results, v)
	}

	fmt.Printf("size=%d, cap=%d, type=%T\n", len(results), cap(results), results)
	for i, v := range results {
		fmt.Printf("%d: %s\n", i, v)
	}
}

或者使用更简洁的读取方式:

func main() {
	var wg sync.WaitGroup
	results := make([]string, 0)

	c1 := make(chan string, 10)
	c2 := make(chan string, 10)
	
	wg.Add(2)
	go Func1(&wg, c1)
	go Func2(&wg, c2)

	wg.Wait()
	close(c1)
	close(c2)

	// 一次性读取所有值
	for {
		select {
		case v, ok := <-c1:
			if ok {
				results = append(results, v)
			} else {
				c1 = nil
			}
		case v, ok := <-c2:
			if ok {
				results = append(results, v)
			} else {
				c2 = nil
			}
		}
		
		if c1 == nil && c2 == nil {
			break
		}
	}

	fmt.Printf("Total items: %d\n", len(results))
	for i, v := range results {
		fmt.Printf("%d: %s\n", i, v)
	}
}

关键点:

  1. <-c1<-c2 只执行一次,所以只读取了一个值
  2. 使用 for range 循环可以读取关闭通道中的所有剩余值
  3. 缓冲通道只是缓冲,不改变通道的基本行为
回到顶部