如何在 Go 中实现序列化?

问题描述 投票:0回答:1

我有一个网络服务器,我想顺序执行一个 REST 调用,它会在网络服务器上创建一些文件。我试图防止客户端多次启动同一个文件的创建,因为它很昂贵。如果客户端尝试创建一个已经在进行中的文件,我想返回 HTTP 423。

我试着按照下面的结构从头开始写

type Procedure[ID comparable] func(ID)

type Sequentialization[ID comparable] struct {
    Meta  sync.Mutex
    Locks map[ID]*sync.Mutex
    Proc Procedure[ID]
}

但现在我想知道我是否是第一个需要这个的人。我在 Go 中有一种惯用的方法来做到这一点,我只是不知道?

go
1个回答
0
投票

这似乎有效。

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

type Procedure[ID comparable, ARG any] func(ID, ARG)

type Sequentialization[ID comparable, ARG any] struct {
    MapMu sync.Mutex
    SeqMu map[ID]*sync.Mutex
    Proc  Procedure[ID, ARG]
}

func NewSequentialization[ID comparable, ARG any](proc Procedure[ID, ARG]) (s *Sequentialization[ID, ARG]) {
    s = new(Sequentialization[ID, ARG])
    s.SeqMu = make(map[ID]*sync.Mutex)
    s.Proc = proc
    return
}

func (s *Sequentialization[ID, ARG]) Exec(id ID, arg ARG) {
    // Create the sequentialization mutex
    s.MapMu.Lock()
    m, exists := s.SeqMu[id]
    if !exists {
        m = new(sync.Mutex)
        s.SeqMu[id] = m
    }
    p := s.Proc
    s.MapMu.Unlock()

    // Sequentialize work
    (*m).Lock()
    p(id, arg)
    (*m).Unlock()

    // Delete the sequentialization mutex
    s.MapMu.Lock()
    delete(s.SeqMu, id)
    s.MapMu.Unlock()
}

func say(id string, arg int) {
    fmt.Print("[")
    for i := 0; i < 5; i++ {
        fmt.Print(arg)
        time.Sleep(100 * time.Millisecond)
    }
    fmt.Println("]")
}

func main() {
    s := NewSequentialization(say)
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        r := rand.Intn(90) + 10
        fmt.Println(r)
        wg.Add(1)
        go func() {
            defer wg.Done()
            s.Exec("id", r)
        }()
    }
    wg.Wait()
}
© www.soinside.com 2019 - 2024. All rights reserved.