ホームページ >バックエンド開発 >Golang >Go 同時プログラミングのユースケースとシナリオの詳細な説明

Go 同時プログラミングのユースケースとシナリオの詳細な説明

WBOY
WBOYオリジナル
2024-06-02 13:38:56564ブラウズ

Go では goroutine を介して並行プログラミングが実装されており、複数のタスクを同時に実行して効率を向上させることができます。その使用例は次のとおりです: 並列処理 イベント処理 I/O 集中型操作 HTTP サービス タスク スケジューリング

Go 同時プログラミングのユースケースとシナリオの詳細な説明

Go 同時プログラミングの使用例とシナリオの詳細な説明

はじめに
同時プログラミングは、次のことを可能にするプログラミング パラダイムです。複数のタスクを同時に実行します。 Go 言語では、軽量スレッドであるゴルーチンを通じて同時プログラミングが実装されます。この記事では、Go での同時プログラミングのユースケースとシナリオを調査し、実践的な例を示します。

ユースケースとシナリオ

1. 並列処理

  • 大きなタスクを小さなサブタスクに分割し、並列処理して効率を高めます。
  • 例: ゴルーチンを使用して画像処理タスクを並列化します。

2. イベント処理

  • 受信イベントをリッスンし、Goroutine を使用して各イベントを並列処理します。
  • 例: Goroutine を使用して WebSocket 接続からの受信メッセージを処理します。

3. I/O 集中型の操作

  • ファイル読み取りやネットワーク呼び出しなどの I/O 集中型操作の場合、Goroutine を使用するとパフォーマンスを向上させることができます。
  • 例: Goroutine を使用して複数のファイルからデータを並行して読み取ります。

4. HTTP サービス

  • HTTP サービスでは、Goroutine を使用して受信リクエストを処理すると、同時実行性が向上します。
  • 例: Goroutine を使用して、Web サーバーから受信した HTTP リクエストを処理します。

5. タスクのスケジュール

  • Goroutine を使用して、特定の時間または定期的に実行する必要があるタスクを管理およびスケジュールします。
  • 例: 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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。