临时锁定资源,直到 goroutine 完成

Temporary lock the resource until goroutine is finished

我有一个方法,它发送 HTTP 状态代码 202 Accepted 作为请求成功的指示,并在其中运行另一个进程(goroutine)。类似的东西:

return func(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusAccepted)
    go func() {
        time.Sleep(2 * time.Second)
    }()
}

我想暂时锁定资源,防止goroutine进程多次执行

return func(w http.ResponseWriter, r *http.Request) {
    c := make(chan bool)

    select {
    case _, unlocked := <-c:
        if unlocked {
            break
        }
    default:
        w.WriteHeader(http.StatusLocked)
        return
    }

    w.WriteHeader(http.StatusAccepted)
    go func(c chan bool) {
        time.Sleep(2 * time.Second)
        c <- true
    }(c)
}

我总是收到 423 Locked 状态码。我想,我还不了解渠道。可以尝试使用互斥量吗?

不是最好的解决方案,但它有效:

func (h *HookHandler) NewEvents() http.HandlerFunc {
    eventsLocker := struct {
        v   bool
        mux *sync.Mutex
    }{
        v:   true,
        mux: &sync.Mutex{},
    }

    return func(w http.ResponseWriter, r *http.Request) {
        if !eventsLocker.v {
            w.WriteHeader(http.StatusLocked)
            return
        }

        w.WriteHeader(http.StatusAccepted)

        go func() {
            defer eventsLocker.mux.Unlock()
            defer func() { eventsLocker.v = true }()

            eventsLocker.mux.Lock()
            eventsLocker.v = false

            time.Sleep(2 * time.Second)
        }()
    }
}