第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

傳遞什么上下文來(lái)等待某事完成?

傳遞什么上下文來(lái)等待某事完成?

Go
紅糖糍粑 2022-07-11 14:51:57
由于種種原因,我覺(jué)得http.ListenAndServe不適合我的需要。我需要能夠確定綁定的地址和端口(即使用時(shí)":0"),所以我引入了一個(gè)net.Listener,讀取listener.Addr()然后傳遞給http.Serve(listener, nil)。然后我需要能夠使用不同的 URL 處理程序運(yùn)行兩個(gè) HTTP 服務(wù)器,所以我引入了一個(gè)http.NewServeMux(),添加了必要的mux.HandleFunc("/path", fn)處理程序,并傳遞為http.Serve(listener, mux).然后我需要能夠干凈地停止這些服務(wù)器,并關(guān)閉任何連接,獨(dú)立于主程序本身,所以現(xiàn)在我介紹了&http.Server{Handler: mux}哪些我可以go func() { server.Serve(listener) }()。理論上,我可以通過(guò)調(diào)用來(lái)阻止它server.Shutdown(ctx),但現(xiàn)在import "context"似乎沒(méi)有一個(gè)可用的上下文提供我想要的。我希望能夠等到干凈關(guān)閉完成,然后繼續(xù)我的代碼。我的理解是我應(yīng)該能夠<- ctx.Done()實(shí)現(xiàn)這一點(diǎn),但我已經(jīng)嘗試了兩者context.Background(),context.TODO()而且似乎都沒(méi)有“觸發(fā)” ctx.Done(),我最終永遠(yuǎn)阻塞了。其他context選項(xiàng)似乎是基于時(shí)間的。如果我不等待或通過(guò),似乎完成得太快,我看不到任何東西實(shí)際上是關(guān)閉的()nilserver.Shutdown(ctx)runtime.Numgoroutine() != 1我可以time.Sleep(duration)任意持續(xù)一段時(shí)間,但我不想要任意持續(xù)時(shí)間。我想知道server.Shutdown已經(jīng)干凈地完成了。package mainimport (    "fmt"    "net"    "net/http"    "runtime"    "time")func main() {    var err error    listener, err := net.Listen("tcp", "localhost:0")    fmt.Printf("Listening on http://%v\n", listener.Addr())    mux := http.NewServeMux()    mux.HandleFunc("/", handleIndex)    stop, err := startHTTPServer(listener, mux)    d, _ := time.ParseDuration("5s")    time.Sleep(d)   // delay here just for example of "long-running" server    close(stop)     // closing the channel returned by my helper should trigger shutdown    time.Sleep(d)   // if this delay is here, I see the "Stopped" message    if err != nil {        panic(err)    }    fmt.Printf("End of program, active goroutines: %v", runtime.NumGoroutine())}我都試過(guò)了context.Background()和context.TODO()。我試過(guò)new(context.Context)了,但那拋出了一個(gè)SIGSEGV. 我試過(guò)nil了,根本不用等。我嘗試添加 a sync.WaitGroupand 調(diào)用wg.Wait()而不是 second time.Sleep(d),但我仍然需要等到server.Shutdown()完成后再調(diào)用wg.Done()(并且defer wg.Done()調(diào)用它太早了)。我覺(jué)得,對(duì)于 Contexts、WaitGroups 等,我只是在代碼中添加了一些雜亂無(wú)章的東西,而沒(méi)有真正理解為什么它們是必要的。等待server.Shutdown完成的正確、干凈、慣用的方法是什么?
查看完整描述

2 回答

?
滄海一幻覺(jué)

TA貢獻(xiàn)1824條經(jīng)驗(yàn) 獲得超5個(gè)贊

要在主 goroutine 中等待 Shutdown 完成,請(qǐng)從該 goroutine 調(diào)用 Shutdown。消除通道和額外的 goroutine。


listener, _ := net.Listen("tcp", "localhost:0")

fmt.Printf("Listening on http://%v\n", listener.Addr())


mux := http.NewServeMux()

mux.HandleFunc("/", handleIndex)


server := &http.Server{Handler: mux}

go func() {

    fmt.Println("Starting server...")

    err := server.Serve(listener)

    if err != nil && err != http.ErrServerClosed {

        log.Fatal(err)

    }

}()


time.Sleep(5 * time.Second) // delay here just for example of "long-running" server


// Shutdown and wait for server to complete.

server.Shutdown(context.Background())

如果要限制 Shutdown 等待服務(wù)器關(guān)閉的時(shí)間,請(qǐng)?zhí)鎿Qcontext.Background()為使用截止日期創(chuàng)建的上下文。


查看完整回答
反對(duì) 回復(fù) 2022-07-11
?
撒科打諢

TA貢獻(xiàn)1934條經(jīng)驗(yàn) 獲得超2個(gè)贊

理論上,我可以通過(guò)調(diào)用 server.Shutdown(ctx) 來(lái)阻止它,但現(xiàn)在 import "context" 中的任何可用上下文似乎都不能提供我想要的。我希望能夠等到干凈關(guān)閉完成,然后繼續(xù)我的代碼。


這意味著您應(yīng)該傳遞一個(gè)不會(huì)超時(shí)的上下文。既不context.Background()也不context.TODO()超時(shí),因此是合適的(真的,見(jiàn)下文)。您是否使用其中一個(gè)取決于您是否計(jì)劃超時(shí)關(guān)閉(您應(yīng)該防止粗糙的客戶(hù)端阻止您關(guān)閉您的服務(wù)器)。


我的理解是我應(yīng)該能夠 <- ctx.Done() 來(lái)實(shí)現(xiàn)這一點(diǎn),但我已經(jīng)嘗試了 context.Background() 和 context.TODO() 并且似乎都沒(méi)有“觸發(fā)”ctx.Done(),我最終永遠(yuǎn)阻塞了。其他上下文選項(xiàng)似乎是基于時(shí)間的。


嗯,這個(gè)是錯(cuò)的。也context.Background()不會(huì)context.TODO()關(guān)閉它們Done,因?yàn)樗鼈儾粫?huì)超時(shí)。但是不需要 等待 done: 是一個(gè)正常的函數(shù),一旦服務(wù)器實(shí)際正確關(guān)閉(這就是你想要的)或上下文超時(shí),它就會(huì)返回。無(wú)論如何只是返回。server.Shutdownserver.Shutdown


一個(gè)簡(jiǎn)單的


server.Shutdown(context.TODO())

是你想要的。(現(xiàn)在,從長(zhǎng)遠(yuǎn)來(lái)看:傳遞一個(gè)在很長(zhǎng)但有限的時(shí)間后超時(shí)的上下文。)


但是無(wú)論如何,您的代碼看起來(lái)都很可疑:您的 func startHTTPServer 沒(méi)有正確處理錯(cuò)誤:不是啟動(dòng)錯(cuò)誤,也不是停止錯(cuò)誤。如果您的服務(wù)器沒(méi)有啟動(dòng),您將無(wú)法停止它,您的代碼只會(huì)吞下錯(cuò)誤。犯錯(cuò)也很活潑。您的問(wèn)題可能不是來(lái)自傳遞給 server.Shutdown 的上下文,而是來(lái)自其他地方。


問(wèn)題是你的代碼沒(méi)有等待 server.Shutdown 返回,因?yàn)檫@個(gè)函數(shù)是在一個(gè) goroutine 中啟動(dòng)的,沒(méi)有任何同步回 startHTTPServer 的調(diào)用者:不要那樣做。真的: server.Shutdown 的上下文不是問(wèn)題。


以下是未經(jīng)測(cè)試的代碼,它稍微克服了這些問(wèn)題。正如您在所有 TOOD 中看到的那樣,它還沒(méi)有準(zhǔn)備好生產(chǎn)。


// startHTTPServer is a helper function to start a server and returns

// a channel to stop the server and a channel reporting errors during

// starting/stopping the server or nil if the server was shut down

// properly

func startHTTPServer(listener net.Listener, handler http.Handler) (stop chan bool, problems chan error) {

    stop, problems = make(chan bool), make(chan error)

    server := &http.Server{Handler: handler} // TODO: set timeouts


    go func() {

        fmt.Println("Starting server...")

        err := server.Serve(listener)

        if err != http.ErrServerClosed {

            problems <- err // TODO: tag/classify as startup error

        }

    }()

    go func() {

        select {

        case <-stop:

            fmt.Println("Stop channel closed; stopping server...")

            err := server.Shutdown(context.TODO())

            fmt.Println("Stopped.")

            problems <- err // TODO: tag/classify as shutdown error

        case e := <-problems:

            problems <- e  // resend, this error  is not for us

            return // stop waiting for stop as server did not start anyway.

        }

    }()

    return stop, problems

}


其他解決方案也是可能的,例如返回單獨(dú)的啟動(dòng)和關(guān)閉錯(cuò)誤通道等。


查看完整回答
反對(duì) 回復(fù) 2022-07-11
  • 2 回答
  • 0 關(guān)注
  • 146 瀏覽
慕課專(zhuān)欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)