在Go语言中,switch语句是一种条件控制结构,用于根据不同的条件执行不同的代码块,它比多个if-else语句更加清晰和易于管理。它有以下几个特点:

分支逻辑自动结束:当一个case分支匹配成功后,Go会自动结束switch语句,不需要显式地使用break来跳出。

支持多种条件表达式类型:在Go中,switch的条件表达式不局限于常见的整型或字符型,也可以是字符串等其他类型。

支持多值匹配:一个case可以同时匹配多个值,这些值使用逗号分隔。

支持无表达式语法:Go语言的switch也可以不带条件表达式,这种情况下,它等同于switch true,这样可以用作更复杂的条件判断。

支持fallthrough关键字强制执行:在Go中,可以使用fallthrough关键字强制执行下一个case的代码块,但请小心使用,因为这可能导致代码逻辑不清晰。

1. 基本语法

switch语句的基本语法如下:

switch expression {
case value1:
    // 当expression等于value1时执行这里的代码
case value2:
    // 当expression等于value2时执行这里的代码
...
default:
    // 当没有匹配的case时执行这里的代码
}

2. 分支逻辑自动结束

package main

import (
    "fmt"
)

func main() {
    fruit := "apple"

    switch fruit {
    case "apple":
        fmt.Println("This is an apple.")
        // 在这里不需要break,Go会自动退出switch
    case "banana":
        fmt.Println("This is a banana.")
    case "orange":
        fmt.Println("This is an orange.")
    default:
        fmt.Println("Unknown fruit.")
    }
}

输出结果如下,不需要显式地使用break来跳出。

This is an apple.

3. 支持多种条件表达式类型

package main

import (
    "fmt"
)

func handleType(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Printf("The integer is %d\n", v)
    case string:
        fmt.Printf("The string is %s\n", v)
    case float64:
        fmt.Printf("The float is %f\n", v)
    case bool:
        fmt.Printf("The boolean is %t\n", v)
    default:
        fmt.Println("Unknown type")
    }
}

func main() {
    handleType(42)
    handleType("hello")
    handleType(3.14)
    handleType(true)
}

输出结果

The integer is 42
The string is hello
The float is 3.140000
The boolean is true

上述逻辑中,

  • handleType函数接受一个空接口interface{}类型的参数,这意味着它可以接收任何类型的变量。

  • switch语句中,我们使用.(type)语法来获取参数的实际类型。

  • 对于每一种预期的类型(intstringfloat64bool),我们编写了一个相应的case来处理它。

  • 如果传入的类型不在这些case中,就会执行default块,并打印"Unknown type"。

4. 支持多值匹配

package main

import (
    "fmt"
)

func main() {
    day := "Thursday"

    switch day {
    case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
        fmt.Println(day, "is a weekday.")
    case "Saturday", "Sunday":
        fmt.Println(day, "is a weekend.")
    default:
        fmt.Println(day, "is not a valid day.")
    }
}

输出结果

Thursday is a weekday.
  • switch语句中,为工作日和周末分别设置了不同的case
  • 如果day是"Monday"、“Tuesday”、“Wednesday”、"Thursday"或者"Friday"中的任意一个,它将匹配第一个case并打印出是工作日。
  • 如果day是"Saturday"或者"Sunday",则匹配第二个case并打印出是周末。

5. 支持无表达式语法

无表达式的switch实际上就是不带条件的switch语句,它默认的比较对象是true。这种类型的switch可以用于替代长串的if-else语句,使代码更加清晰。

package main

import (
    "fmt"
    "time"
)

func main() {
    hour := time.Now().Hour()

    switch {
    case hour < 12:
        fmt.Println("Good morning!")
    case hour < 17:
        fmt.Println("Good afternoon!")
    default:
        fmt.Println("Good evening!")
    }
}

输出结果

Good morning!
  • 根据当前小时数的不同,switch会匹配不同的case
  • 如果小时数小于12,打印"Good morning!"
  • 如果小时数小于17,打印"Good afternoon!“,其他情况下,打印"Good evening!”

6. 支持fallthrough关键字强制执行

在Go语言中,fallthrough关键字用于在switch语句中强制执行下一个case块的内容,即使下一个case的条件并未满足。这是Go语言特有的一个特性,与其他语言中的switch语句有所不同。

package main

import (
    "fmt"
)

func main() {
    number := 3

    switch number {
    case 1:
        fmt.Println("One")
    case 2:
        fmt.Println("Two")
        fallthrough
    case 3:
        fmt.Println("Three")
        fallthrough
    case 4:
        fmt.Println("Four")
    case 5:
        fmt.Println("Five")
    default:
        fmt.Println("Unknown Number")
    }
}

输出结果

Three
Four

代码逻辑

  • number为1时,只打印"One"。
  • number为2时,将打印"Two",然后由于fallthrough,继续执行下一个case,也就是打印"Three"。
  • number为3时,打印"Three",然后由于fallthrough,继续执行下一个case,也就是打印"Four"。
  • number为4或5时,只打印对应的"Four"或"Five"。
  • 如果number不匹配任何case,则打印"Unknown Number"。

需要注意的是,fallthrough不会检查下一个case的条件是否满足,它会无条件地执行下一个case的代码块。因此,使用fallthrough时需要谨慎,以避免逻辑错误。

7. switch 和 select搭配使用

select语句select语句在Go中是与协程(goroutines)和通道(channels)密切相关的一个控制结构。它用于处理多个通道的发送和接收操作。当select有多个case时,它会随机选择一个可执行的case执行。如果没有case可执行,它将阻塞,直到有case可执行。以下程序创建了两个通道channel1channel2,使用两个协程向这两个通道发送不同的消息,主函数中的select语句监听这两个通道的消息,当从任一通道接收到消息时,调用handleMessage函数,并使用switch语句来根据通道名称处理消息。

package main

import (
    "fmt"
    "time"
)

func main() {
    // 创建两个通道
    channel1 := make(chan string)
    channel2 := make(chan string)

    // 启动一个协程向channel1发送数据
    go func() {
        time.Sleep(1 * time.Second)
        channel1 <- "Message from Channel 1"
    }()

    // 启动另一个协程向channel2发送数据
    go func() {
        time.Sleep(2 * time.Second)
        channel2 <- "Message from Channel 2"
    }()

    // 使用select来监听两个通道
    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-channel1:
            handleMessage("Channel1", msg1)
        case msg2 := <-channel2:
            handleMessage("Channel2", msg2)
        }
    }
}

// handleMessage 使用switch语句来处理不同通道的消息
func handleMessage(channelName, message string) {
    switch channelName {
    case "Channel1":
        fmt.Println("Received from", channelName, ":", message)
    case "Channel2":
        fmt.Println("Received from", channelName, ":", message)
    default:
        fmt.Println("Unknown channel")
    }
}

输出结果

Received from Channel1 : Message from Channel 1
Received from Channel2 : Message from Channel 2

欢迎来公账号交流,共同学习,共同进步!

更多文章见公众号

Logo

欢迎加入西安开发者社区!我们致力于为西安地区的开发者提供学习、合作和成长的机会。参与我们的活动,与专家分享最新技术趋势,解决挑战,探索创新。加入我们,共同打造技术社区!

更多推荐