掌握Golang中的select语句实现并发编程

 更新时间:2023年04月18日 10:02:58   作者:西直门三太子  
Golang中的select语句用于在多个通道间选择可读或可写的操作,并阻塞等待其中一个通道进行操作。可以用于实现超时控制、取消和中断操作等。同时,select语句支持default分支,用于在没有任何通道可操作时执行默认操作

序文

select 是用来配合channel使用的

空select

  • 没有内容的select 会阻塞
  • 没有内容是指,没有case,也没有default
  • 如果没有其它的任务指执行,将会触发死锁
package main
import (
    "fmt"
    "time"
)
/**
* 没有内容的select 会阻塞
* 没有内容是指,没有case,也没有default
* 如果没有其它的任务指执行,将会触发死锁
*/
func main() {
    go func() {
        time.Sleep(2 * time.Second)
        fmt.Println("没有内容的select 会阻塞")
    }()
    select {}
}

只有default的select

只有default的select 和串行化没有区别

package main
import "fmt"
/**
 只有default的select 和串行化没有区别
 */
func main() {
	go func() {
		fmt.Println("quick")
	}()
	select {
	default:
		fmt.Println("end")
	}
}

带 case 的 select

有case,有 default

  • 如果能匹配到case 就 执行 case
  • 匹配不到case,就执行default
  • 有 default,就代表了不会阻塞
package main
import (
	"fmt"
)
func main() {
	ch1 := make(chan int, 2)
	ch2 := make(chan int, 2)
	select {
	case v1 := <-ch1:
		fmt.Println(v1)
	case v2 := <-ch2:
		fmt.Println(v2)
	default:
		fmt.Println(22)
	}
}

package main
import (
	"fmt"
	"time"
)
func main() {
	ch1 := make(chan int, 2)
	ch2 := make(chan int, 2)
	go func() {
		ch1 <- 1
	}()
	time.Sleep(1 * time.Second)
	select {
	case v1 := <-ch1:
		fmt.Printf("get v1 chan value %d", v1)
	case v2 := <-ch2:
		fmt.Printf("get v1 chan value %d", v2)
	default:
		fmt.Println(22)
	}
}

有case,无default

会阻塞 一直等到case匹配上

package main
import (
	"fmt"
	"time"
)
func main() {
	ch1 := make(chan int, 2)
	ch2 := make(chan int, 2)
	fmt.Printf("start unix:%d \n", time.Now().Unix())
	go func() {
		time.Sleep(3 * time.Second)
		ch1 <- 1
	}()
	select {
	case v1 := <-ch1:
		fmt.Printf("case unix: %d \n", time.Now().Unix())
		fmt.Printf("get v1 chan value %d \n", v1)
	case v2 := <-ch2:
		fmt.Printf("get v1 chan value %d \n", v2)
	}
	fmt.Println("end")
}

select 只匹配一次,如果要进行 n > 1 的 匹配,使用 for + select

package main
import (
	"fmt"
	"time"
)
func main() {
	ch1 := make(chan int, 2)
	ch2 := make(chan int, 2)
	fmt.Printf("start unix:%d \n", time.Now().Unix())
	go func() {
		for {
			time.Sleep(1 * time.Second)
			ch1 <- 1
		}
	}()
	for {
		select {
		case v1 := <-ch1:
			fmt.Printf("case unix: %d \n", time.Now().Unix())
			fmt.Printf("get v1 chan value %d \n", v1)
		case v2 := <-ch2:
			fmt.Printf("get v1 chan value %d \n", v2)
		}
	}
}

匹配是无序的

package main
import (
	"fmt"
	"time"
)
func test() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	go func() {
		ch1 <- 1
		close(ch1)
	}()
	go func() {
		time.Sleep(1 * time.Second)
		ch2 <- 1
		close(ch2)
	}()
	time.Sleep(2 * time.Second)
	// 如果有顺序,那么因该每次都是v1
	select {
	case v1 := <-ch1:
		fmt.Printf("case unix: %d \n", time.Now().Unix())
		fmt.Printf("get v1 chan value %d \n", v1)
	case v2 := <-ch2:
		fmt.Printf("case unix: %d \n", time.Now().Unix())
		fmt.Printf("get v2 chan value %d \n", v2)
	}
}
func main() {
	for i := 0; i < 10; i++ {
		test()
	}
}

到此这篇关于掌握Golang中的select语句实现并发编程的文章就介绍到这了,更多相关Golang中的select语句内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go语言基础Json序列化反序列化及文件读写示例详解

    Go语言基础Json序列化反序列化及文件读写示例详解

    这篇文章主要为大家介绍了Go语言基础Json序列化反序列化以及文件读写的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-11-11
  • 一文教你打造一个简易的Golang日志库

    一文教你打造一个简易的Golang日志库

    这篇文章主要为大家详细介绍了如何使用不超过130行的代码,通过一系列golang的特性,来打造一个简易的golang日志库,感兴趣的小伙伴可以了解一下
    2023-06-06
  • 从零封装Gin框架配置初始化全局变量

    从零封装Gin框架配置初始化全局变量

    这篇文章主要为大家介绍了从零封装Gin框架配置初始化全局变量,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • 详解golang中make与new的异同点和用法

    详解golang中make与new的异同点和用法

    这篇文章将给大家介绍了go语言中函数new与make的使用和区别,关于go语言中new和make是内建的两个函数,主要用来创建分配类型内存,文中通过代码示例介绍的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2024-01-01
  • 9个Golang中map常用示例分享

    9个Golang中map常用示例分享

    这篇文章主要和大家分享9个Golang中map可能是常用的使用案例,从1到9,越来越厉害。文中的示例代码讲解详细,希望对大家学习Golang有一定的帮助
    2023-02-02
  • Golang sync包中errgroup的使用详解

    Golang sync包中errgroup的使用详解

    Go 语言为我们提供了丰富的并发原语,且大多数都位于 sync 包下,今天我们来探讨一下该库下的原语之一:errgroup,感兴趣的小伙伴可以了解一下
    2023-05-05
  • go mongox简洁高效文档操作及bson数据构造流畅技巧

    go mongox简洁高效文档操作及bson数据构造流畅技巧

    这篇文章主要为大家介绍了go mongox简洁高效文档操作及bson数据构造流畅技巧示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Go语言实现对XML的读取和修改

    Go语言实现对XML的读取和修改

    这篇文章主要为大家详细介绍了Go语言实现对XML的读取和修改的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • goland 设置project gopath的操作

    goland 设置project gopath的操作

    这篇文章主要介绍了goland 设置project gopath的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • 利用Golang解析json数据的方法示例

    利用Golang解析json数据的方法示例

    Go提供了原生的JSON库,并且与语言本身有效的集成在了一起。下面这篇文章将给大家介绍关于利用Golang解析json数据的方法,文中给出了详细的示例代码供大家参考学习,需要的朋友们下面跟着小编来一起学习学习吧。
    2017-07-07

最新评论