在Linux环境下,使用Golang实现并发编程主要依赖于Go语言的轻量级线程——goroutines和通道(channels)。以下是一些关键概念和示例代码:
Goroutines是Go语言中实现并发的基本单位。它们比传统的操作系统线程更轻量级,可以轻松创建成千上万个。
package main
import (
"fmt"
"time"
)
func printNumbers() {
for i := 1; i <= 5; i++ {
fmt.Printf("Number: %d\n", i)
time.Sleep(1 * time.Second)
}
}
func main() {
go printNumbers() // 启动一个新的goroutine
// 主goroutine继续执行
time.Sleep(6 * time.Second)
fmt.Println("Main function finished")
}
Channels是goroutines之间通信和同步的主要方式。它们可以用来传递数据,确保goroutines之间的有序执行。
package main
import (
"fmt"
"time"
)
func producer(ch chan<- int) {
for i := 1; i <= 5; i++ {
ch <- i // 将数据发送到通道
time.Sleep(1 * time.Second)
}
close(ch) // 关闭通道
}
func consumer(ch <-chan int) {
for num := range ch { // 从通道接收数据,直到通道关闭
fmt.Printf("Received: %d\n", num)
}
}
func main() {
ch := make(chan int)
go producer(ch) // 启动生产者goroutine
go consumer(ch) // 启动消费者goroutine
time.Sleep(6 * time.Second)
fmt.Println("Main function finished")
}
select语句用于在多个通道操作中进行选择,类似于switch语句,但用于通道。
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch1 <- "from ch1"
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- "from ch2"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
}
}
}
sync包提供了一些同步原语,如WaitGroup、Mutex等,用于更复杂的并发控制。
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // 确保在函数结束时调用Done()
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1) // 增加WaitGroup的计数器
go worker(i, &wg)
}
wg.Wait() // 等待所有goroutines完成
fmt.Println("All workers done")
}
通过这些基本概念和示例代码,你可以在Linux环境下使用Golang实现高效的并发编程。