掌握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语句内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入理解Golang的单元测试和性能测试

    深入理解Golang的单元测试和性能测试

    Go语言提供了强大的测试工具,下面这篇文章主要给大家介绍了关于Golang单元测试和性能测试的相关资料,文中通过示例代码给大家详细介绍了单元测试和性能测试的相关内容,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-08-08
  • Go语言小白入门刷题打印输出沙漏

    Go语言小白入门刷题打印输出沙漏

    这篇文章主要介绍了Go语言刷题打印输出沙漏的示例过程详解,非常适合刚入门Go语言的小白学习,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-11-11
  • GO语言实现文件上传的示例代码

    GO语言实现文件上传的示例代码

    这篇文章主要分享一下golang实现文件上传的流程和具体代码,供大家参考,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助
    2022-08-08
  • Go字典使用详解

    Go字典使用详解

    今天和大家一起学习Go语言的字典。Go语言的字典又称为map,一种使用广泛的数据结构。它是拥有key/value对元素的「无序集合」,而且在集合中key必须是唯一的
    2022-11-11
  • Go ORM的封装解决方式详解

    Go ORM的封装解决方式详解

    这篇文章主要为大家介绍了Go ORM的封装解决方式详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Golang在Mac、Linux、Windows下如何交叉编译的实现

    Golang在Mac、Linux、Windows下如何交叉编译的实现

    这篇文章主要介绍了Golang在Mac、Linux、Windows下如何交叉编译的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • Golang实现自己的Redis(pipeline客户端)实例探索

    Golang实现自己的Redis(pipeline客户端)实例探索

    这篇文章主要为大家介绍了Golang实现自己的Redis(pipeline客户端)实例探索,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • golang模拟实现带超时的信号量示例代码

    golang模拟实现带超时的信号量示例代码

    这篇文章主要给大家介绍了关于golang模拟实现带超时的信号量的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面跟着小编来一起学习学习吧。
    2017-09-09
  • Go 语言结构体链表的基本操作

    Go 语言结构体链表的基本操作

    链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,这篇文章主要介绍了Go 语言结构体链表,需要的朋友可以参考下
    2022-04-04
  • Go Gin框架优雅重启和停止实现方法示例

    Go Gin框架优雅重启和停止实现方法示例

    Web应用程序中,有时需要重启或停止服务器,无论是因为更新代码还是进行例行维护,这时需要保证应用程序的可用性和数据的一致性,就需要优雅地关闭和重启应用程序,即不丢失正在处理的请求和不拒绝新的请求,本文将详解如何在Go语言中使用Gin这个框架实现优雅的重启停止
    2024-01-01

最新评论