首页 > 其他分享 >Golang基础-Select

Golang基础-Select

时间:2023-04-05 22:57:51浏览次数:38  
标签:基础 Select Golang abort 回车 channel done ticker select

基本概念

  • select 是 Go 中的一个控制结构,类似于 switch 语句。
  • select 语句只能用于通道(channel)操作,每个 case 必须是一个通道操作,要么是发送要么是接收。
  • select 语句会监听所有指定的通道上的操作,一旦其中一个通道准备好就会执行相应的代码块。
  • 如果多个通道都准备好,那么 select 语句会随机选择一个通道执行。如果所有通道都没有准备好,那么执行 default 块中的代码。

select监听一堆channel,哪个channel来数据了就执行相应的代码。来数据了就是就绪,就是有人往channel里写数据了。

例子

下面的代码模拟火箭发射倒计时程序,倒数10秒没人中断就发射,否则终止。终止的操作是按键盘的回车,用一个goroutine监听是否有这个操作。这个等待回车的goroutine实际上是阻塞了,直到输入回车才停止阻塞,继续执行下面的代码。
通过新建一个名为abort的channel来表示是否有人按下回车终止发射。一旦有人按下回车,上面说的那个等待输入的处于阻塞状态的goroutine就继续执行下一行代码,也就是往abort这个channel里写数据。(注意这里的空结构体作用)abort一旦数据就绪,可以被读取,那么select就有机会选择相应的代码块执行,这部分代码就是终止发射。
注意ticker.C也是一个channel,每隔一秒往里面写一条数据。for循环每隔一秒打印一次倒数数据,为什么是一秒?因为select的两个case都是阻塞的,ticker.C等待一秒变得就绪,abort则是有人输入回车才会就绪。所以最终结果就是,如果一直没人输入回车,这个select只有等ticker等一秒变得就绪才能继续执行。所以每次for循环都会阻塞一秒钟。
ticker最后要stop,否则一直往channel里写数据。goroutine泄露?可以想象成这个ticker也是一个goroutine,如果不stop,那么他一直存活,尽管我们的程序已经不需要用他了,但他还是默默无闻地往channel里写数据。

package main

import (
	"fmt"
	"os"
	"time"
)

func launch() {
	fmt.Println("Launching rockets")
}

func main() {
	abort := make(chan struct{})
	go func() {
		os.Stdin.Read(make([]byte, 1))
		abort <- struct{}{}
	}()

	fmt.Println("Commencing countdown.  Press return to abort.")
	ticker := time.NewTicker(1 * time.Second)
	for countdown := 10; countdown > 0; countdown-- {
		fmt.Println(countdown)
		select {
		case <-ticker.C: // receive from the ticker's channel
			// Do nothing.
		case <-abort:
			fmt.Println("Launch aborted!")
			return
		}
	}
	ticker.Stop() // cause the ticker's goroutine to terminate
	launch()
}

下面是另一个例子。这个例子演示了生产者消费者模式。通过done channel来通知select结束监听。这里是直接close(done),因为读一个已经关闭的channel,会读到0值,如果还写了ok的话,会读到false。其实这么写我觉得不太好,还不如往done里写一条数据容易理解。
done这个channel,如果没有外部干扰,是一直处于非就绪的状态,没有东西可以读。但是,一旦将他关闭,我们就能读到相应的0值。我们这里只关心能不能读,不关系读出来什么,所以用close能实现一样的效果。

func main() {
    messages := make(chan int, 10)
    done := make(chan bool)

    defer close(messages)
    // consumer
    go func() {
        ticker := time.NewTicker(1 * time.Second)
        for _ = range ticker.C {
            select {
            case <-done:
                fmt.Println("child process interrupt...")
                return
            default:
                fmt.Printf("send message: %d\n", <-messages)
            }
        }
    }()

    // producer
    for i := 0; i < 10; i++ {
        messages <- i
    }
    time.Sleep(5 * time.Second)
    close(done)
    time.Sleep(1 * time.Second)
    fmt.Println("main process exit!")
}

标签:基础,Select,Golang,abort,回车,channel,done,ticker,select
From: https://www.cnblogs.com/roadwide/p/17291213.html

相关文章

  • MYSQL基础知识之函数
     1、函数概念函数是指一段可以直接被另一段程序调用的程序或代码2、字符串函数MySQL常用的字符串函数有:# CONCAT(S1,S2,...Sn):字符串拼接,将S1,S2,...Sn拼接成一个字符串SELECTCONCAT('hello','world'); #LOWER(str):将字符串str全部转为小写SELECTLOWER('ABCD');......
  • Python基础(四)爬虫
    python爬虫系列文章网上搜素的系列文章记录一下后续可能会用https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzI3NzI1MzY4Mw==&action=getalbum&album_id=1786298272630816773#wechat_redirect1.requests请求2.User-Agent伪装from selenium import webdriverheader......
  • 45、K8S-调度机制-节点调度之nodeAffinity、nodeName、nodeSelector
    Kubernetes学习目录1、配置解析1.1、简介我们知道,默认的调度策略有可能无法满足我们的需求,我们可以根据实际情况,定制自己的调度策略,然后整合到k8s的集群中。1.2、属性解析apiVersion:kubescheduler.config.k8s.io/v1beta1kind:KubeSchedulerConfigurationAlgorithmSou......
  • Golang入门教程(一)GOPATH与工作空间(Windows)
    https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/01.2.md Windows环境:下面我就以mymath为例来讲述如何编写应用包:cd$GOPATH/srcmkdirmymath//我的环境:$GOPATH=c:\mygo新建文件sqrt.go,内容如下://$GOPATH/src/mymath/sqrt.go源码如......
  • PHP基础知识之————PHP Web脚本中使用FFmpeg
    简介本文将尝试指出在PHPWeb脚本中使用FFmpeg时需要了解的所有重要事项。它还将显示一些使用示例,以使事情更清楚。这个想法也可以应用到其他web脚本语言。从PHP脚本调用命令行工具选择一个模型网页设计为快速执行,以便浏览您的网站的人不必等待太多的响应。因为如果他们无聊的等待,......
  • 理论基础知识之————KB Kb Kbps 相关单位的区别和换算
    换算公式 8bit(位)=1Byte(字节)1024Byte(字节)=1KB1024KB=1MB1024MB=1GB1024GB=1TB 容量是大写的 B而传输的速度是小写的 bbps 是bitspersecond的缩写,表示比特/秒。    Bps 是bitypersecond的缩写,表示字节/秒。    这个p又可以写成/, S是秒的缩写,所......
  • JavaScript基础知识之——Location 对象详解
    属性描述location.hash设置或取得URL中的锚location.host设置或取得URL中主机(包括端口号)location.hostname设置或取得URL中的主机名location.href设置或取得完整URL(页面重定向应用)location.pathname设置或取得URL中的路径location.port设置或取得URL中的端口号location.......
  • Redis基础知识之—— 缓存应用场景
    一、MySql+Memcached架构的问题Memcached采用客户端-服务器的架构,客户端和服务器端的通讯使用自定义的协议标准,只要满足协议格式要求,客户端Library可以用任何语言实现。Memcached服务器使用基于Slab的内存管理方式,有利于减少内存碎片和频繁分配销毁内存所带来的开销。各个Slab按需......
  • Java基础知识点(代码块)
    一:代码块的分类局部代码块、构造代码块、静态代码块。1.局部代码块publicclassTest{publicstaticvoidmain(String[]args){{}inta=20;System.out.println(a);//这一部分就是局部代码块}}2.构造代码块publicclassSt......
  • 2.Visual studio的使用和C++的基础
    visualstudio的基础介绍C++入门编程C++关键字、标识符C++基本数据类型变量的定义visualstudio的基础介绍解决方案资源管理器 也可以在”视图”中找到”解决方案资源管理器” “.h”:头文件;“.cpp”:源文件添加新建项,选择C++语言  运行程序,或"ctrl+F5“ ......