首頁  >  文章  >  後端開發  >  Go並發程式設計的使用案例與場景詳解

Go並發程式設計的使用案例與場景詳解

WBOY
WBOY原創
2024-06-02 13:38:56490瀏覽

並發程式設計在 Go 中透過 goroutine 實現,允許同時執行多個任務,提高效率。其用例包括:並行處理事件處理I/O 密集型操作HTTP 服務任務調度

Go並發程式設計的使用案例與場景詳解

#Go 並發程式設計的用例與場景詳解

#簡介
並發程式設計是一種程式設計範式,它允許我們同時執行多個任務。在 Go 語言中,並發程式設計透過 goroutine 實現,goroutine 是輕量級線程。本篇文章將探討 Go 中並發程式設計的用例和場景,並提供實際範例。

使用案例與場景

1. 並行處理

  • 將大型任務分解為較小的子任務並並行處理它們,以提高效率。
  • 範例:使用 Goroutines paralleize 圖片處理任務。

2. 事件處理

  • 監聽傳入事件並使用 goroutine 並行處理每個事件。
  • 範例:使用 Goroutines 處理來自 WebSocket 連線的傳入訊息。

3. I/O 密集型操作

  • #對於I/O 密集型操作,例如檔案讀取或網路調用,使用Goroutines可以提高性能。
  • 範例:使用 Goroutines 從多個檔案中並行讀取資料。

4. HTTP 服務

  • 在 HTTP 服務中,使用 Goroutines 處理傳入請求可以提高並發性。
  • 範例:用 Goroutines 處理來自 Web 伺服器的傳入 HTTP 請求。

5. 任務排程

  • 使用 Goroutines 管理和排程需要在特定時間或週期性執行的任務。
  • 範例:使用 Goroutine 實作 Cron 定時器來排程作業。

實戰範例

範例1:並發圖片處理

package main

import (
    "fmt"
    "image"
    "image/color"
    "image/draw"
    "runtime"
)

func main() {
    width, height := 1000, 1000
    images := []image.Image{}

    // 并行创建 100 个图像
    for i := 0; i < 100; i++ {
        img := image.NewRGBA(image.Rect(0, 0, width, height))
        draw.Draw(img, img.Bounds(), &image.Uniform{color.RGBA{0, 0, 0, 255}}, image.ZP, draw.Src)
        images = append(images, img)
    }

    // 计算创建图像所花费的时间
    numCPUs := runtime.NumCPU()
    start := time.Now()
    for i := 0; i < 100; i++ {
        go createImage(images[i])
    }

    // 等待所有 Goroutine 完成
    time.Sleep(10 * time.Second)
    elapsed := time.Since(start)
    fmt.Printf("Creating %d images using %d CPUs took %s\n", len(images), numCPUs, elapsed)
}

func createImage(img image.Image) {
    // 模拟耗时的图像处理操作
    time.Sleep(500 * time.Millisecond)
}

範例2:處理WebSocket訊息

package main

import (
    "errors"
    "fmt"
    "net/http"
    "sync/atomic"

    "github.com/gorilla/websocket"
)

type client struct {
    conn *websocket.Conn
    name string
}

var (
    upgrader = websocket.Upgrader{}
    messages = make(chan string)
)

var connectedClients uint64

func main() {
    http.HandleFunc("/websocket", serveWebSocket)

    // 启动 Goroutine 来处理传入消息
    go handleMessage()

    if err := http.ListenAndServe(":8080", nil); err != nil {
        fmt.Println(err)
    }
}

func serveWebSocket(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    atomic.AddUint64(&connectedClients, 1)

    go handleConnection(conn)
}

func handleConnection(conn *websocket.Conn) {
    defer func() {
        conn.Close()
        atomic.AddUint64(&connectedClients, -1)
    }()

    // 监听来自客户端的消息
    for {
        _, message, err := conn.ReadMessage()
        if err != nil {
            if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
                fmt.Println(err)
            }
            return
        }

        messages <- message
    }
}

func handleMessage() {
    for message := range messages {
        // 处理消息逻辑
        fmt.Println("Received message:", message)

        // 例如,将消息广播给所有已连接的客户端
        for clients.Range(func(_, v interface{}) bool {
            client := v.(client)
            if err := client.conn.WriteMessage(websocket.TextMessage, []byte(message)); err != nil {
                if errors.Is(err, websocket.ErrCloseSent) {
                    clients.Delete(client.name)
                    fmt.Printf("Client %s disconnected\n", client.name)
                }
            }
            return true
        }) { }
    }
}

以上是Go並發程式設計的使用案例與場景詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn