Go,你也可以的!-【6.3 select】

6.3 select

select一般是与goroutinechannel一起使用的。

它的主要作用是用来从多个channel中读取数据。

相当于使用一个goroutine通过select来读取多个channel的数据。

如果所有channel都没有数据,那么就会阻塞,直到其中一个channel有数据为止。

如果多个channel都有数据,那么就会随机从其中一个先读取数据。

本节代码存放目录为 lesson18

select使用

在上一节中我们已经讲到了channel,接下来我们将演示select如何使用。代码如下所示:

func main() {
	var (
		wg               sync.WaitGroup
		numberChan       chan int
		numberBufferChan chan int
	)
	numberChan = make(chan int)
	numberBufferChan = make(chan int, 5)

	wg.Add(1)
	go func() {
		defer wg.Done()
		for i := 0; i < 10; i++ {
			fmt.Printf("写入数据: %d\n", i)
			numberChan <- i
			time.Sleep(time.Duration(1) * time.Second)
		}
		close(numberChan)
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		for i := 100; i < 110; i++ {
			fmt.Printf("写入数据Buffer: %d\n", i)
			numberBufferChan <- i
			time.Sleep(time.Duration(1) * time.Second)
		}
		close(numberBufferChan)
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case number1, ok := <-numberChan:
				if !ok {
					numberChan = nil
				} else {
					fmt.Printf("读取数据: %d\n", number1)
				}
			case number2, ok := <-numberBufferChan:
				if !ok {
					numberBufferChan = nil
				} else {
					fmt.Printf("读取数据Buffer: %d\n", number2)
				}
			}
			if numberChan == nil && numberBufferChan == nil {
				break
			}
		}
	}()

	wg.Wait()
}

在上面的代码中,我们创建了两个通道,通过两个协程进行通道数据的发送。

之后我们开启了另一个协程,通过select读取两个通道的数据。

上面的例子演示了select的常用操作,另外的用法就是我们在学习goroutine时所使用到的select{}

其实select{}也是利用了自身的这一特点,从而让主线程一直阻塞,直到所有的协程都执行完毕。

小结

select在日常场景中使用不算多,不过在一些复杂的业务场景中,比如支付场景,使用的还是比较多的。

本节总结如下:

  • select用于同时读取多个通道的数据

  • 用法与switch类似,但是不能在case里面使用break,否则整个协程都会退出

  • 通道没有数据时会进行阻塞,这时候如果定义了default,就会执行default里面的代码

  • 多个通道都有数据时,程序会基于公平性的原则,随机选择一个读取

书籍地址:https://youcan.golang.website/

书籍代码:https://github.com/YouCanGolang

我的GitHub:https://github.com/swxctx

你可能感兴趣的:(Go,你也可以的!,golang,数据库,开发语言,Go,你也可以的!)