Select 语句
select 是 Go 中的一个控制结构,类似于 switch 语句。
select 语句只能用于通道操作,每个 case 必须是一个通道操作,要么是发送要么是接收。
select 语句会监听所有指定的通道上的操作,一旦其中一个通道准备好就会执行相应的代码块。
如果多个通道都准备好,那么 select 语句会随机选择一个通道执行。如果所有通道都没有准备好,那么执行 default 块中的代码。
Go 编程语言中 select 语句的语法如下:
select {
case <- channel1:
// 执行的代码
case value := <- channel2:
// 执行的代码
case channel3 <- value:
// 执行的代码
// 你可以定义任意数量的 case
default:
// 所有通道都没有准备好,执行的代码
}
<-
<- 是一个 channel 操作符,用于在 channel 中接收或发送数据。具体来说,<- 有两种主要的用途:
1. 接收数据:<-channel 用来从一个 channel 中接收数据。
• 例如:msg1 := <-c1 表示从 c1 channel 中接收数据,并将其存储在变量 msg1 中。
2. 发送数据:channel <- value 用来将数据发送到一个 channel 中。
• 例如:c1 <- "one" 表示将字符串 "one" 发送到 c1 channel。
channel
在 Go 语言中,channel(通道)是一种用于在不同的 goroutine 之间进行通信的机制。它允许一个 goroutine 将数据发送到另一个 goroutine,而不需要使用显式的锁或共享内存。通道是 Go 并发模型的核心部分,用于协调不同 goroutine 之间的工作。
可以将 channel 看作是一个管道,数据从一个 goroutine 通过管道流向另一个 goroutine。通过这种方式,goroutine 之间可以安全地共享数据。
主要特点:
1. 类型安全:每个 channel 都有一个类型,表示它能传递的数据类型。例如,chan int 表示只能传递 int 类型数据的 channel。
2. 同步机制:channel 也提供了同步机制。当一个 goroutine 向 channel 发送数据时,它会被阻塞,直到另一个 goroutine 从该 channel 接收到数据为止,反之亦然。这意味着发送和接收操作是同步的,确保数据的正确传递。
3. 无锁并发:与传统的共享内存模型相比,channel 提供了一种通过通信而非共享内存来实现并发的方法,避免了显式的锁。
Channel 的基本用法
1. 创建 Channel:
使用 make(chan T) 来创建一个 channel,T 是数据类型,表示该 channel 能传输的数据类型。
c := make(chan int) // 创建一个传递 int 类型数据的 channel
c <- 42 // 将 42 发送到 c channel 中
示例
package main
import (
"fmt"
"time"
)
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
c1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
}
}
}
以上代码执行结果为:
received one
received two
goto
Go 语言的 goto 语句可以无条件地转移到过程中指定的行。
goto 语句通常与条件语句配合使用。可用来实现条件转移, 构成循环,跳出循环体等功能。
但是,在结构化程序设计中一般不主张使用 goto 语句, 以免造成程序流程的混乱,使理解和调试程序都产生困难。
语法
goto 语法格式如下:
goto label;
..
.
label: statement;
标签
标签(label)是一个标识符,后面跟着一个冒号 (:),用来标记程序中的某个位置。标签本身并不执行任何操作,它主要用于和 goto、break、continue 等控制流语句一起使用,来控制程序的跳转。
package main
import "fmt"
func main() {
fmt.Println("开始")
// 使用 goto 跳转到 "end" 标签处
goto end
fmt.Println("这行代码不会执行")
end:
fmt.Println("跳转到标签处")
}