GO基础进阶篇 (十)、channel

channel

1.关闭通道

通道被关闭后,再去获取通道的值。会得到通道的零值,如果是引用类型,则会得到nil。

package main

import (
	"fmt"
)

func main() {

	ch := make(chan int)

	go test(ch)

	for {
		v, ok := <-ch
		if !ok {
			fmt.Println("通道已关闭")
			break
		}
		fmt.Println("读取到的数据", v)
	}

	fmt.Println("读取到的数据1", <-ch) 
	for v := range ch {
		fmt.Println("读取到的数据", v)
	}
}

func test(ch chan int) {
	for i := 0; i < 10; i++ {
		ch <- i
	}
	close(ch)
}

2. 缓冲通道

缓冲通道在Go语言中有多种用途,它们主要涉及到异步通信、流量控制和协调多个goroutine之间的工作。以下是一些缓冲通道的通用用途:

  1. 异步通信: 缓冲通道可以用于实现异步通信,允许发送和接收操作在不同的时间进行。发送操作将数据放入缓冲通道,而接收操作可以随后在程序的执行中处理这些数据。这对于解耦生产者和消费者的速率很有用,因为它们可以以不同的速度工作。

  2. 流量控制: 缓冲通道可用于进行流量控制,限制数据在通道中的流动。当缓冲通道已满时,发送操作将会阻塞,直到有空间可用。这使得你可以有效地控制数据的流量,防止某一方快速产生数据导致另一方难以跟上。

  3. 协调工作: 缓冲通道可以用于协调多个goroutine之间的工作。通过在通道中缓冲一定数量的任务或消息,可以实现工作者池、并发任务分发等场景。这种方式可以有效地控制同时进行的工作数量。

  4. 解耦发送和接收: 缓冲通道允许发送和接收操作在不同的goroutine中进行,从而提高程序的并发性。这种解耦有助于编写更灵活和可维护的代码。

  5. 防止goroutine泄漏: 在无缓冲通道中,发送和接收操作必须同时准备好,否则它们会发生阻塞。在某些情况下,这可能导致goroutine泄漏。使用缓冲通道可以避免这种情况,因为即使没有接收方,发送方仍然可以将数据放入缓冲通道而不被阻塞。

package main

import (
	"fmt"
	"strconv"
	"time"
)

func main() {

	ch1 := make(chan int)
	fmt.Println(len(ch1), cap(ch1))

	ch2 := make(chan int, 5)
	fmt.Println(len(ch2), cap(ch2))

	ch2 <- 1
	ch2 <- 1
	ch2 <- 1
	ch2 <- 1
	ch2 <- 1
	fmt.Println(len(ch2), cap(ch2))
	//ch2 <- 1  缓冲区为5,第六条存入时,会触发死锁。

	//先缓存4条,再去读
	ch3 := make(chan string, 4)
	go test(ch3)
	for v := range ch3 {
		time.Sleep(time.Second)
		fmt.Println(v)
	}
}

func test(ch chan string) {
	for i := 0; i < 10; i++ {
		ch <- "test" + strconv.Itoa(i)
		fmt.Println("写入的数据", "test"+strconv.Itoa(i))
	}
	close(ch)
}

3.定向通道(单向)

只能接收或发送数据的通道。

package main
import (
	"fmt"
	"time"
)

func main() {
	ch1 := make(chan int)

	go writeOnly(ch1)
	go readOnly(ch1)

	time.Sleep(time.Second)
}

func writeOnly(ch chan<- int) {
	ch <- 100
}

func readOnly(ch <-chan int) {
	data := <-ch
	fmt.Println(data)
}

你可能感兴趣的:(GO语言从基础到应用,golang,开发语言,后端)