3 回答

TA貢獻1878條經驗 獲得超4個贊
是的,如果我不阻止它,你的觀點“c) 是正確的” 。
為了保存響應編寫器,您不應該在其中調用 go routine。相反,您應該將ServeHTTP作為 go-routine 調用,大多數 http 服務器實現都這樣做。
這樣你就不會阻止任何 api 調用,每個 api 調用將在不同的 go-routine 中運行,被它們的功能阻止。
由于您的“jobs chan QueueElement”是單個通道(不是緩沖通道),因此您的所有進程都在“gv.jobs <- newPrintJob”處被阻塞。
您應該使用緩沖通道,以便所有 api 調用都可以將其添加到隊列中并根據工作完成或超時獲得響應。
擁有緩沖通道也可以模擬打印機在現實世界中的內存限制。(隊列長度 1 是特例)

TA貢獻1817條經驗 獲得超6個贊
我已經為您的代碼添加了一些更新?,F在它像你描述的那樣工作。
package main
import (
"database/sql"
"fmt"
"log"
"math/rand"
"net/http"
"sync"
"time"
)
type QueueElement struct {
jobid string
rw http.ResponseWriter
doneChan chan struct{}
}
type GlobalVars struct {
db *sql.DB
wg sync.WaitGroup
jobs chan QueueElement
}
func (gv *GlobalVars) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/StartJob":
fmt.Printf("incoming\r\n")
doneC := make(chan struct{}, 1) //Buffered channel in order not to block the worker routine
go func(doneChan chan struct{}, w http.ResponseWriter) {
gv.jobs <- QueueElement{
doneChan: doneC,
jobid: "jobid",
}
}(doneC, w)
select {
case <-time.Tick(time.Second * 5):
fmt.Fprintf(w, "job is taking more than 5 seconds to complete\r\n")
fmt.Printf("took longer than 5 secs\r\n")
case <-doneC:
fmt.Fprintf(w, "instant reply from serveHTTP\r\n")
fmt.Printf("instant\r\n")
}
default:
fmt.Fprintf(w, "No such Api")
}
}
func worker(jobs <-chan QueueElement) {
for {
job := <-jobs
fmt.Println("START /i /b try.cmd")
fmt.Printf("job done")
randTimeDuration := time.Second * time.Duration(rand.Intn(7))
time.Sleep(randTimeDuration)
// processExec("START /i /b processAndPrint.exe -" + job.jobid)
job.doneChan <- struct{}{}
}
}
func main() {
// create a GlobalVars instance
gv := GlobalVars{
//db: db,
jobs: make(chan QueueElement),
}
go worker(gv.jobs)
// create an http.Server instance and specify our job manager as
// the handler for requests.
server := http.Server{
Handler: &gv,
Addr: ":8888",
}
// start server and accept connections.
log.Fatal(server.ListenAndServe())
}
- 3 回答
- 0 關注
- 166 瀏覽
添加回答
舉報