Go 学习笔记(62)— Go 中 switch 语句中的 switch 表达式和 case 表达式之间的关系

switch 语句对 switch 表达式的结果类型,以及各个 case 表达式中子表达式的结果类型都是有要求的。

毕竟,在 Go 语言中,只有类型相同的值之间才有可能被允许进行判等操作。

1. switch 类型和 case 类型不匹配

1.1 switch 类型和 case 类型不能转换场景

package main

import "fmt"

func main() {
	value1 := [...]int8{0, 1, 2, 3, 4, 5, 6}
	switch 1 + 3 { // 这条语句无法编译通过。
	case value1[0], value1[1]:
		fmt.Println("0 or 1")
	case value1[2], value1[3]:
		fmt.Println("2 or 3")
	case value1[4], value1[5], value1[6]:
		fmt.Println("4 or 5 or 6")
	}

}

输出结果:

invalid case value1[0] in switch on 1 + 3 (mismatched types int8 and int)
invalid case value1[1] in switch on 1 + 3 (mismatched types int8 and int)

原因是:
switch 表达式的结果值是无类型的常量,比如 1 + 3 的求值结果就是无类型的常量 4 ,那么这个常量会被自动地转换为此种常量的默认类型的值,比如整数 4 的默认类型是 int ,又比如浮点数 3.14 的默认类型是 float64

因此,由于上述代码中的 switch 表达式的结果类型是 int ,而那些 case 表达式中子表达式的结果类型却是 int8 ,它们的类型并不相同,所以这条 switch 语句是无法通过编译的。

1.2 switch 类型和 case 类型可以转换场景

package main

import "fmt"

func main() {

	value2 := [...]int8{0, 1, 2, 3, 4, 5, 6}
	fmt.Printf("value2[4] type is %T\n ", value2[4])
	switch value2[4] {
	case 0, 1:
		fmt.Println("0 or 1")
	case 2, 3:
		fmt.Println("2 or 3")
	case 4, 5, 6:
		fmt.Println("4 or 5 or 6")
	}
}

输出结果:

value2[4] type is int8
 4 or 5 or 6

switch 表达式的结果值是 int8 类型的,而那些 case 表达式中子表达式的结果值却是无类型的常量了。这与之前的情况恰恰相反。

能够编译成功的原因是,如果 case 表达式中子表达式的结果值是无类型的常量,那么它的类型会被自动地转换为 switch 表达式的结果类型,又由于上述那几个整数都可以被转换为 int8 类型的值,所以对这些表达式的结果值进行判等操作是没有问题的。

总结:
类型自动转换

  • 如果 switch 表达式后面的是无类型的值,它不会发生自动转换类型。
  • 但是如果 case 后面的是无类型的值的话会被自动转换成 switch 后面的类型。

2. case 表达式中的子表达式不能重复(只针对结果值为常量的子表达式)

switch 语句不允许 case 表达式中的子表达式结果值存在相等的情况,不论这些结果值相等的子表达式,是否存在于不同的 case 表达式中,都会是这样的结果。

package main

import "fmt"

func main() {

	value3 := [...]int8{0, 1, 2, 3, 4, 5, 6}
	switch value3[4] { // 这条语句无法编译通过。
	case 0, 1, 2:
		fmt.Println("0 or 1 or 2")
	case 2, 3, 4:
		fmt.Println("2 or 3 or 4")
	case 4, 5, 6:
		fmt.Println("4 or 5 or 6")
	}
}

编译错误:

duplicate case 2 in switch
duplicate case 4 in switch

3. case 表达式中的子表达式不是常量时则可以重复

package main

import "fmt"

func main() {

	value5 := [...]int8{0, 1, 2, 3, 4, 5, 6}
	switch value5[4] {
	case value5[0], value5[1], value5[2]:
		fmt.Println("0 or 1 or 2")
	case value5[2], value5[3], value5[4]:
		fmt.Println("2 or 3 or 4")
	case value5[4], value5[5], value5[6]:
		fmt.Println("4 or 5 or26")
	}
}

输出结果:

2 or 3 or 4

只要 switch 表达式的结果值与某个 case 表达式中的任意一个子表达式的结果值相等,该 case 表达式所属的 case 子句就会被选中。并且,一旦某个 case 子句被选中,其中的附带在 case 表达式后边的那些语句就会被执行。与此同时,其他的所有case子句都会被忽略。

不过,这种绕过方式对用于类型判断的 switch 语句(以下简称为类型switch语句)就无效了。因为类型 switch 语句中的 case 表达式的子表达式,都必须直接由类型字面量表示,而无法通过间接的方式表示。代码如下:

package main

import "fmt"

func main() {

	value6 := interface{}(byte(127))
	switch t := value6.(type) { // 这条语句无法编译通过。
	case uint8, uint16:
		fmt.Println("uint8 or uint16")
	case byte: // duplicate case byte in type switch
		fmt.Printf("byte")
	default:
		fmt.Printf("unsupported type: %T", t)
	}
}

原因是:
byte 类型是 uint8 类型的别名类型。因此,它们两个本质上是同一个类型,只是类型名称不同罢了。

在这种情况下,这个类型 switch 语句是无法通过编译的,因为子表达式 byteuint8 重复了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言,正则表达式可以通过`regexp`包来实现。该包提供了一组函数和方法,用于编译和匹配正则表达式。你可以使用`regexp.Compile`函数来编译正则表达式,然后使用`MatchString`方法来匹配字符串。例如,下面的代码演示了如何在Go语言使用正则表达式: ```go package main import ( "fmt" "regexp" ) func main() { // 编译正则表达式 re := regexp.MustCompile(`\d+`) // 匹配字符串 match := re.MatchString("12345") fmt.Println(match) // 输出: true } ``` 在上面的例子,我们使用`regexp.MustCompile`函数编译了一个正则表达式`\d+`,该表达式用于匹配一个或多个数字。然后,我们使用`MatchString`方法来检查字符串"12345"是否匹配该正则表达式。最后,我们打印出匹配结果,结果为`true`示匹配成功。 除了`MatchString`方法,`regexp`包还提供了其他一些方法,如`FindString`、`FindAllString`、`ReplaceAllString`等,用于在字符串查找、替换符合正则表达式的内容。你可以根据具体的需求选择合适的方法来使用正则表达式。 #### 引用[.reference_title] - *1* [Go语言 正则表达式](https://blog.csdn.net/weixin_44226181/article/details/125924743)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Go语言学习笔记——正则表达式](https://blog.csdn.net/qq_39280718/article/details/126696265)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Go语言——正则表达式](https://blog.csdn.net/ekcchina/article/details/124965398)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值