go语言条件语句switch与select

本文详细介绍了Go语言中的switch语句和select语句。switch语句提供了灵活的条件判断,而select语句则专注于处理channel的通信,允许在多个IO操作中随机公平地选择一个执行。在没有可用case时,select会阻塞,有default子句则会执行default流程,否则程序会等待直到有case可执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、switch语句

 go中switch的几种用法如下面代码示例所示:

package main

import (
	"fmt"
)

func main() {
	var x interface{}
	//用type-switch语句来判断某个interface变量中实际存储的变量类型

	//写法一:
	switch i := x.(type) { //带初始化语句
	case nil:
		fmt.Printf("x的类型:%T\r\n", i)
	case int:
		fmt.Printf("x是int类型")
	case float64:
		fmt.Printf("x是float64类型")
	case func(int) float64:
		fmt.Printf("x是func(int)类型")
	case bool, string:
		fmt.Printf("x是bool或string类型")
	default:
		fmt.Printf("未知类型")
	}

	//写法二
	var j = 0
	switch j {
	case 0:
	case 1:
		fmt.Println("1")
	case 2:
		fmt.Println("2")
	default:
		fmt.Println("def")
	}

	//写法三
	var k = 0
	switch  k  {
	case 0:
		println("fallthrough")
		fallthrough
		/*
		   Go的switch非常灵活,表达式不必是常量或整数,执行的过程从上至下,直到找到匹配项;
		   而如果switch没有表达式,它会匹配true。
		   Go里面switch默认相当于每个case最后带有break,
		   匹配成功后不会自动向下执行其他case,而是跳出整个switch,
		   但是可以使用fallthrough强制执行后面的case代码。
		*/
	case 1:
			fmt.Println("1")
	case 2:
			fmt.Println("2")
	default:
		fmt.Println("def")
	}

	//写法四
	var m = 0
	switch  m {
	case 0, 1:
		fmt.Println("1")
	case 2:
		fmt.Println("2")
	default:
		fmt.Println("def")
	}

	//写法五
	var n = 0
	switch { //省略条件表达式,可当成if...else if...else
	case n > 0 && n < 10:
		fmt.Println("i > 0 and i < 10")
	case n > 10 && n < 20:
		fmt.Println("i > 10 and i < 20")
	default:
		fmt.Println("def")
	}
}

执行结果:

 

二、select语句

  1. select语句类似于switch语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。

      select可以监听channel的数据流动,用于处理异步IO操作,它最大的限制就是每个case语句里必须是一个IO操作(channel操作)

      select是Go中的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接收。一个默认的子句应该总是可运行的。

  2. select的语法可用以下几句话简单表示:

     (1) 每个case都必须是一个通信

     (2) 所有channel表达式都会被求值

     (3)  所有被发送的表达式都会被求值

     (4) 如果任意某个通信可以执行,它就执行;其他被忽略

     (5) 如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行

     否则:

     (1) 如果有default子句,则执行该语句。

     (2) 如果没有default子句,select将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。

3. 在一个select语句中,Go会按顺序从头到尾评估每一个发送和接收的语句。如果其中的任意一个语句可以继续执行(即没有被阻塞),那么就从那些可执行的语句中任意选择一条来使用。

   如果没有任何一条语句可以执行(即所有通道都被阻塞),那么有两种可能的情况:

(1)如果给出了default语句,那么就会执行default的流程,同时程序的执行会从select语句后的语句中恢复(即继续执行select之外的代码)。

(2)如果没有default语句,那么select语句将被阻塞,直到至少有一个case可以进行下去

几种用法:

1. 基本用法

//1.基本使用
	var c1, c2, c3 chan int
	var i1, i2 int
	select {
	case i1 = <-c1:
		fmt.Printf("received ", i1, "from c1\n")
	case c2 <- i2:
		fmt.Printf("sent ", i2, " to c2\n")
	case i3, ok := (<-c3):
		if ok {
			fmt.Printf("received ", i3, " from c3\n")
		} else {
			fmt.Printf("c3 is closed\n")
		}
	default:
		fmt.Printf("no communication\n")
	}

2.  几种典型用法

(1) 超时判断

//比如在下面的场景中,使用全局resChan来接收response,如果时间超过3s,resChan中还没有数据返回,则第二条case将执行
var resChan = make(chan int)
//do request
func testTimeOut() {
	select {
	case data := <-resChan:
		fmt.Println(data)
	case <-time.After(time.Second * 3):
			fmt.Println("request time out")
	}
}

(2)遇到特定事件时退出程序

//2.退出
var shouldQuit = make(chan struct{})
func testExit() {
	select {
	case <-shouldQuit:
		//cleanup
		return
	}
}

(3) 判断channel是否阻塞

//3.判断channel是否阻塞
func testBlock() {
	ch := make(chan int, 5)
	data := 0
	select {
	case ch <- data:
	default:
		fmt.Println("丢弃data")
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值