网站域名跳转是怎么做的,wordpress 文章数据,物流门户网站开发 报价,触屏网站开发教程1、channel是什么#xff1f;
管道或者是通道。字面意思也就是说是传输的通道或者是管道。 在 Go 语言中#xff0c;channel 的关键字为 chan#xff0c;数据流向的表现方式为 - 分为两种模式#xff1a; 双向– 表现形式为#xff1a;chan T#xff0c;即双向通道。…1、channel是什么
管道或者是通道。字面意思也就是说是传输的通道或者是管道。 在 Go 语言中channel 的关键字为 chan数据流向的表现方式为 - 分为两种模式 双向– 表现形式为chan T即双向通道。 单向– 表现形式有两种。分别是:chan - T表示只允许发送的通道T - chan表示只允许接收的通道。 除此之外channel分为缓冲通道和无缓冲通道。
// 无缓冲
ch1 : make(chan int)// 缓冲区为 3
ch2 : make(chan int, 3)2、无缓冲channel
缓冲区大小默认为0。 在Go语言中无缓冲的channel是一种在发送和接收操作之间同步进行的通道。无缓冲channel保证了数据的传递几乎是即时的发送操作会阻塞直到另一端的goroutine执行接收操作反之亦然。这种特性使得无缓冲channel成为goroutine之间同步操作和通信的理想选择。#### 如何创建
ch : make(chan int)如何使用
var ch make(chan string)go func() {ch - 包子}()msg : -chfmt.Println(msg)在上面的代码中发送操作在另一个goroutine中执行它会阻塞直到主goroutine执行接收操作。
特性是什么
无缓冲channel的一个关键特性是它们在发送和接收数据时提供了同步保证。 当数据从一个goroutine通过无缓冲channel发送到另一个goroutine时发送者goroutine会阻塞直到接收者goroutine接收了数据这确保了在两个goroutine之间的数据交换是同步的。
使用场景
需要确保在数据处理过程中两个goroutine能够同步操作时。用来通知一个goroutine另一个goroutine的事件已经发生比如任务完成或是需要停止执行。
注意事项
会发生死锁的两种情况
没有goroutine接收发送过来的数据没有goroutine发送数据
3、有缓冲channel
和无缓冲相比多了一个缓冲区域。 无缓冲channel用来同步有缓冲的channel用来异步。 在Go语言中有缓冲的channel允许在阻塞发送和接收操作之前存储一个固定数量的值。这种类型的channel是异步的只有在缓冲区满时发送操作才会阻塞只有在缓冲区空时接收操作才会阻塞。
如何使用
当向有缓冲channel发送数据时如果缓冲区未满发送操作就会立即完成并且发送goroutine可以继续执行不会阻塞。如果缓冲区已满发送操作将会阻塞直到有空间可用。从有缓冲channel接收数据时如果缓冲区中有数据接收操作会立即提取数据并继续执行。如果缓冲区为空接收操作将会阻塞直到有数据可读。
应用场景是什么
解耦生产者和消费者的处理速度当生产者和消费者处理数据的速率不一致时有缓冲的channel可以作为中间存储减少直接的依赖。流量控制通过限制缓冲区的大小可以在一定程度上控制程序的内存使用防止因为生产速度远大于消费速度而导致的内存溢出。批量处理有时等待直到有足够的数据积累在缓冲区中之后再批量处理可以提高处理效率。
注意事项
缓冲区大小要合适。太小会导致频繁阻塞太大会增加内存使用。甚至在生产者速度远大于消费者速度时导致内存泄漏即使channel是有缓冲的也应避免在没有接收方时向channel发送数据这可能会导致发送goroutine永久阻塞从而造成goroutine泄漏。
4、如何判断goroutine是否关闭
在Go语言中并没有内置的方法去检测是否关闭。 有3种模式可以间接地帮助理解goroutine是否已经完成了它的执行任务:
使用sync.WaitGroup
var wg sync.WaitGroupwg.Add(1)go func() {// goroutine完成时调用defer wg.Done()// 执行任务}()// 等待所有goroutine全部结束每个都调用donewg.Wait()当wait返回时表示相关的goroutine已经全部完成了。
使用channel
// 根据Go规范空结构体不分配内存也就是说不占用空间
// 只是一个信号没有其他意义
done : make(chan struct{})// 启动一个goroutine等待信号go func() {-done // 等待信号不关心传递的数据fmt.Println(Received signal, exiting.)}()// 发送信号close(done)使用context
如果你的goroutine是响应取消信号而结束的那么可以通过检查context的状态来判断goroutine是否已经结束。
ctx, cancel : context.WithCancel(context.Background())go func() {// 等待取消信号-ctx.Done()// 清理并退出}()// 发出取消信号cancel()在这种情况下当cancel被调用时依赖于这个context的所有goroutine将开始执行退出流程。
5、如何优雅的关闭goroutine? 使用channel发送退出信号
done : make(chan struct{})go func() {for{select {//等待退出信号case -done:// 收到信号退出goroutinereturndefault:// 正常执行任务}}}()// 当需要goroutine结束时关闭channel 并广播给其他goroutineclose(done)使用context包控制多个goroutine
如果多个goroutine使用了同一个context,context包提供了一个优雅的解决方案。你可以创建一个context并在需要停止goroutine时取消它。
ctx, cancel : context.WithCancel(context.Background())go func() {for {select {//检测到取消信号case -ctx.Done():// 退出goroutinereturndefault:// 正常执行任务}}}()//当需要停止goroutine时调用cancel通知使用该context的所有goroutine停止cancel()使用sync.WaitGroup等待goroutine完成优雅关闭
var wg sync.WaitGroupctx, cancel : context.WithCancel(context.Background())wg.Add(1)go func() {defer wg.Done()for {select {//检测到取消信号case -ctx.Done():// 退出goroutinereturndefault:// 正常执行任务}}}()//通知使用该context的所有goroutine停止cancel()// 等待所有goroutine安全退出wg.Wait()