Home >Backend Development >Golang >Detailed explanation of use cases and scenarios of Go concurrent programming

Detailed explanation of use cases and scenarios of Go concurrent programming

WBOY
WBOYOriginal
2024-06-02 13:38:56564browse

Concurrent programming is implemented in Go through goroutine, allowing multiple tasks to be executed at the same time to improve efficiency. Its use cases include: parallel processing event processing I/O intensive operations HTTP service task scheduling

Detailed explanation of use cases and scenarios of Go concurrent programming

Detailed explanation of use cases and scenarios of Go concurrent programming

Introduction
Concurrent programming is a programming paradigm that allows us to perform multiple tasks at the same time. In the Go language, concurrent programming is implemented through goroutines, which are lightweight threads. This article will explore the use cases and scenarios of concurrent programming in Go and provide practical examples.

Use cases and scenarios

1. Parallel processing

  • Decompose large tasks into smaller subtasks and process them in parallel for greater efficiency.
  • Example: Use Goroutines to paralleize image processing tasks.

2. Event processing

  • #Listen to incoming events and use goroutine to process each event in parallel.
  • Example: Use Goroutines to handle incoming messages from WebSocket connections.

3. I/O-intensive operations

  • For I/O-intensive operations, such as file reading or network calls, use Goroutines Can improve performance.
  • Example: Use Goroutines to read data from multiple files in parallel.

4. HTTP service

  • In HTTP service, using Goroutines to handle incoming requests can improve concurrency.
  • Example: Use Goroutines to handle incoming HTTP requests from a web server.

5. Task Scheduling

  • Use Goroutines to manage and schedule tasks that need to be executed at a specific time or periodically.
  • Example: Use Goroutine to implement Cron timer to schedule jobs.

Practical example

Example 1: Concurrent image processing

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)
}

Example 2: Processing WebSocket Message

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
        }) { }
    }
}

The above is the detailed content of Detailed explanation of use cases and scenarios of Go concurrent programming. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn