Go语言中的有缓冲channel和无缓冲channel区别

结论

ch1:=make(chan int)// 无缓冲

ch2:=make(chan int,1)// 有缓冲

无缓冲: 当向ch1中存值后需要其他协程取值,否则一直阻塞

有缓冲: 不会阻塞,因为缓冲大小是1,只有当放第二个值的时候,第一个还没被人拿走,才会阻塞。

测试程序

测试1,声明无缓冲channel

func Test_1(t *testing.T) {
        // 无缓冲
        ch := make(chan int)
        // fatal error: all goroutines are asleep - deadlock! 协程阻塞,需要另一个协程取走channel中的值
        ch <- 1
}

运行结果:

=== RUN   Test_1
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
testing.(*T).Run(0xc0000c0100, 0x55bb8e, 0x6, 0x566b20, 0x47e55d)
        D:/Go/src/testing/testing.go:961 +0x37e
testing.runTests.func1(0xc0000c0000)
        D:/Go/src/testing/testing.go:1202 +0x7f
testing.tRunner(0xc0000c0000, 0xc00008fdc0)
        D:/Go/src/testing/testing.go:909 +0xd0
testing.runTests(0xc000060460, 0x654300, 0x4, 0x4, 0x0)
        D:/Go/src/testing/testing.go:1200 +0x2ae
testing.(*M).Run(0xc0000b6000, 0x0)
        D:/Go/src/testing/testing.go:1117 +0x17d
main.main()
        _testmain.go:50 +0x13c

goroutine 19 [chan send]:
test/review.Test_1(0xc0000c0100)
        E:/Go/src/test/review/main_test.go:64 +0x57
testing.tRunner(0xc0000c0100, 0x566b20)
        D:/Go/src/testing/testing.go:909 +0xd0
created by testing.(*T).Run
        D:/Go/src/testing/testing.go:960 +0x357

Process finished with exit code 1

测试2,开启协程取值

func Test_2(t *testing.T) {
        // 无缓冲
        ch := make(chan int)
        go func() {
                // 睡眠1秒,等待主协程在channel写入值
                time.Sleep(time.Second * 1)
                fmt.Println("开始取值。。。")
                <-ch
        }()
        fmt.Println("开始存值。。。")
        ch <- 1
        time.Sleep(time.Second*5)
        fmt.Println("结束。。。")
}

运行结果:

=== RUN   Test_2
开始存值。。。
开始取值。。。
结束。。。
--- PASS: Test_2 (6.00s)
PASS

Process finished with exit code 0

测试3,声明有缓冲channel

func Test_3(t *testing.T) {
        // 有缓冲
        ch1 := make(chan int, 1)
        // 缓冲大小为1  即是当channel中有一个值时不会被阻塞,当再塞入一个时前一个没被其他协程取走才会阻塞
        ch1 <- 2
        // 此时主协程也可取出值
        fmt.Println(<-ch1)
}

运行结果:

=== RUN   Test_3
2
--- PASS: Test_3 (0.00s)
PASS

Process finished with exit code 0

测试4,存入超过缓冲数量的值

func Test_4(t *testing.T) {
        // 有缓冲
        ch1 := make(chan int, 1)
        // 缓冲大小为1  即是当channel中有一个值时不会被阻塞,当再塞入一个时前一个没被其他携程取走才会阻塞
        ch1 <- 1
        // fatal error: all goroutines are asleep - deadlock!
        ch1 <- 2
}

测试结果:

=== RUN   Test_4
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
testing.(*T).Run(0xc0000a8100, 0x55bba0, 0x6, 0x566b40, 0x47e501)
        D:/Go/src/testing/testing.go:961 +0x37e
testing.runTests.func1(0xc0000a8000)
        D:/Go/src/testing/testing.go:1202 +0x7f
testing.tRunner(0xc0000a8000, 0xc000081dc0)
        D:/Go/src/testing/testing.go:909 +0xd0
testing.runTests(0xc0000044c0, 0x654300, 0x4, 0x4, 0x0)
        D:/Go/src/testing/testing.go:1200 +0x2ae
testing.(*M).Run(0xc00009e000, 0x0)
        D:/Go/src/testing/testing.go:1117 +0x17d
main.main()
        _testmain.go:50 +0x13c

goroutine 6 [chan send]:
test/review.Test_4(0xc0000a8100)
        E:/Go/src/test/review/main_test.go:97 +0x76
testing.tRunner(0xc0000a8100, 0x566b40)
        D:/Go/src/testing/testing.go:909 +0xd0
created by testing.(*T).Run
        D:/Go/src/testing/testing.go:960 +0x357

Process finished with exit code 1