Golang,又称Go语言,以其简洁、高效和并发编程能力著称。掌握Golang的并发编程,能够让你在开发高并发、高性能的网络服务和分布式系统中游刃有余。以下是一些实用的Golang并发编程示例教程,帮助你从入门到精通。
一、基础概念理解
1. goroutine
Goroutine是Go语言并发编程的核心。它是轻量级的线程,由Go运行时管理。
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Println("Goroutine", id)
}(i)
}
wg.Wait()
}
在这个例子中,我们创建了10个goroutine,它们都会打印自己的ID。sync.WaitGroup用于等待所有goroutine执行完成。
2. channel
Channel是goroutine之间的通信机制。
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
go func() {
ch <- 42
}()
fmt.Println(<-ch)
}
这个例子展示了如何通过channel在goroutine之间传递数据。
二、进阶技巧
1. 锁机制
在并发编程中,锁可以保证数据的一致性。
package main
import (
"fmt"
"sync"
)
type SafeCounter struct {
sync.Mutex
Count int
}
func (sc *SafeCounter) Increment() {
sc.Lock()
sc.Count++
sc.Unlock()
}
func main() {
counter := SafeCounter{}
for i := 0; i < 1000; i++ {
go counter.Increment()
}
fmt.Println(counter.Count)
}
在这个例子中,我们使用sync.Mutex来保证SafeCounter的线程安全。
2. context包
context包用于携带上下文信息,例如取消信号、截止时间等。
package main
import (
"context"
"fmt"
"time"
)
func worker(ctx context.Context) {
select {
case <-time.After(5 * time.Second):
fmt.Println("Completed work")
case <-ctx.Done():
fmt.Println("Received cancel")
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
go worker(ctx)
<-time.After(10 * time.Second)
}
在这个例子中,如果worker函数在3秒内未完成,则会接收到取消信号。
三、生产级并发模式
1. 并发Web服务器
使用Golang开发高性能的Web服务器,可以充分利用goroutine。
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
这个简单的HTTP服务器使用goroutine来处理每个请求。
2. 分布式系统
使用Golang开发分布式系统,可以充分利用其并发能力。
package main
import (
"fmt"
"net/rpc"
)
type Args struct {
X, Y int
}
type Quotient struct {
Q, R int
}
func Divide(args Args, reply *Quotient) error {
if args.Y == 0 {
return fmt.Errorf("division by zero")
}
reply.Q = args.X / args.Y
reply.R = args.X % args.Y
return nil
}
func main() {
rpc.RegisterName("DivideService", new(Divide))
rpc.HandleHTTP()
l, e := net.Listen("tcp", ":1234")
if e != nil {
log.Fatal("listen error:", e)
}
fmt.Println("server listening on port 1234")
http.Serve(l, nil)
}
在这个例子中,我们创建了一个简单的RPC服务器,用于执行除法操作。
通过以上示例,你可以逐步掌握Golang的并发编程。在实际项目中,结合你的需求,灵活运用这些技巧,让你的应用更加高效、可靠。
