Go語言的并發模型是其核心特性之一,它通過goroutines和channels提供了一種相對簡單而強大的方式來處理并發任務。下面我將通過幾個案例分析來展示Go語言并發模型的應用。
假設我們要構建一個并發HTTP服務器,該服務器能夠同時處理多個客戶端請求。我們可以使用goroutines來實現這一點。
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處理函數handler
,它只是向客戶端發送一條"Hello, World!"消息。在main
函數中,我們使用http.HandleFunc
將處理函數與路徑"/"
關聯起來,并使用http.ListenAndServe
啟動服務器監聽8080端口。由于HTTP請求是并發的,服務器會為每個請求創建一個新的goroutine來處理,從而實現并發處理。
假設我們要構建一個并發任務調度系統,該系統能夠同時執行多個任務。我們可以使用goroutines和channels來實現這一點。
package main
import (
"fmt"
"sync"
)
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("Worker %d started job %d\n", id, j)
// 模擬任務執行時間
fmt.Printf("Worker %d finished job %d\n", id, j)
results <- j * 2
}
}
func main() {
const numJobs = 5
jobs := make(chan int, numJobs)
results := make(chan int, numJobs)
var wg sync.WaitGroup
for w := 1; w <= 3; w++ {
wg.Add(1)
go worker(w, jobs, results)
}
// 發送任務到jobs通道
for j := 1; j <= numJobs; j++ {
jobs <- j
}
close(jobs)
// 等待所有工作完成
wg.Wait()
// 打印結果
for a := 1; a <= numJobs; a++ {
fmt.Println("Result:", <-results)
}
}
在上面的代碼中,我們定義了一個worker
函數,它從jobs
通道接收任務并執行,然后將結果發送到results
通道。在main
函數中,我們創建了三個工作goroutine,并使用sync.WaitGroup
來等待它們完成。然后,我們向jobs
通道發送任務,并在所有任務完成后關閉通道。最后,我們從results
通道接收并打印結果。
假設我們要構建一個并發文件讀寫系統,該系統能夠同時讀取和寫入多個文件。我們可以使用goroutines和channels來實現這一點。
package main
import (
"fmt"
"io/ioutil"
"os"
"sync"
)
func readFile(filename string, wg *sync.WaitGroup, results chan<- string) {
defer wg.Done()
data, err := ioutil.ReadFile(filename)
if err != nil {
results <- fmt.Sprintf("Error reading %s: %v", filename, err)
return
}
results <- string(data)
}
func writeFile(filename string, data string, wg *sync.WaitGroup) {
defer wg.Done()
err := ioutil.WriteFile(filename, []byte(data), 0644)
if err != nil {
fmt.Printf("Error writing %s: %v\n", filename, err)
return
}
}
func main() {
filenames := []string{"file1.txt", "file2.txt", "file3.txt"}
data := "Hello, World!"
var wg sync.WaitGroup
results := make(chan string, len(filenames))
// 啟動讀取goroutines
for _, filename := range filenames {
wg.Add(1)
go readFile(filename, &wg, results)
}
// 等待讀取完成
go func() {
wg.Wait()
close(results)
}()
// 處理讀取結果
for result := range results {
fmt.Println(result)
}
// 啟動寫入goroutines
for _, filename := range filenames {
wg.Add(1)
go writeFile(filename, data, &wg)
}
// 等待寫入完成
wg.Wait()
fmt.Println("All files have been processed.")
}
在上面的代碼中,我們定義了readFile
和writeFile
函數,分別用于讀取和寫入文件。在main
函數中,我們創建了讀取和寫入goroutines,并使用sync.WaitGroup
來等待它們完成。我們還使用了一個results
通道來收集讀取結果。最后,我們打印處理結果并等待所有寫入操作完成。
這些案例展示了Go語言并發模型的強大功能和靈活性。通過使用goroutines和channels,我們可以輕松地構建并發應用程序,并有效地處理并發任務。