亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

當無法連接時停止通道

當無法連接時停止通道

Go
嚕嚕噠 2023-06-26 16:55:36
我有以下代碼可以正常工作,問題是當連接socket.Connect() 失敗時我想停止該進程,我嘗試使用以下代碼但它不起作用,即如果套接字連接無法連接程序仍然運行。我想要發生的是,如果connect失敗,進程就會停止并且通道......我在這里錯過了什么?func run (appName string) (err error) {        done = make(chan bool)        defer close(done)        serviceURL, e := GetContext().getServiceURL(appName)        if e != nil {            err = errors.New("process failed" + err.Error())            LogDebug("Exiting %v func[err =%v]", methodName, err)            return err        }        url := "wss://" + serviceURL + route        socket := gowebsocket.New(url)        addPass(&socket, user, pass)        socket.OnConnectError = OnConnectErrorHandler        socket.OnConnected = OnConnectedHandler        socket.OnTextMessage = socketTextMessageHandler        socket.OnDisconnected = OnDisconnectedHandler        LogDebug("In %v func connecting to URL  %v", methodName, url)        socket.Connect()        jsonBytes, e := json.Marshal(payload)        if e != nil {            err = errors.New("build process failed" + e.Error())            LogDebug("Exiting %v func[err =%v]", methodName, err)            return err        }        jsonStr := string(jsonBytes)        LogDebug("In %v Connecting to payload JSON is  %v", methodName, jsonStr)        socket.SendText(jsonStr)        <-done        LogDebug("Exiting %v func[err =%v]", methodName, err)        return err    }    func OnConnectErrorHandler(err error, socket gowebsocket.Socket) {        methodName := "OnConnectErrorHandler"        LogDebug("Starting %v parameters [err = %v , socket = %v]", methodName, err, socket)        LogInfo("Disconnected from server ")        done <- true    }該進程應該為運行大約秒的進程打開一個 ws 連接60-90(例如執行 npm install),并通過 t 獲取進程的日志web socke以及何時完成,當然還要處理可能發生的問題,例如網絡問題或運行時的某些錯誤過程
查看完整描述

2 回答

?
慕蓋茨4494581

TA貢獻1850條經驗 獲得超11個贊

好的,發生的情況是當您嘗試向通道添加內容時通道被阻塞。嘗試done使用緩沖區(我使用 1)初始化通道,如下所示:

done = make(chan bool, 1)


查看完整回答
反對 回復 2023-06-26
?
阿波羅的戰車

TA貢獻1862條經驗 獲得超6個贊

您將看到OnConnectErrorHandler在執行調用期間同步調用Connect().?在連接完全建立并且回調完成之前,該Connect()函數不會啟動單獨的 goroutine 來處理 websocket 。OnConnected因此,當您嘗試寫入無緩沖的通道時done,您會阻塞最初調用該函數的同一個Goroutine,并且您自己會陷入僵局,因為沒有 Goroutine 能夠從通道讀取數據來解鎖您。run()

因此,您可以采用他的解決方案并將其轉換為緩沖通道,這將起作用,但我的建議是不要針對這種一次性標志行為寫入通道,而是使用信號發送close。為每個要終止的條件定義一個通道run(),并在相應的 websocket 處理函數中close定義該條件發生時的通道。在底部run(),您可以select打開所有通道,并在第一個通道關閉時退出。它看起來像這樣:

package main


import "errors"


func run(appName string) (err error) {


? ? // first, define one channel per socket-closing-reason (DO NOT defer close these channels.)

? ? connectErrorChan := make(chan struct{})

? ? successDoneChan := make(chan struct{})

? ? surpriseDisconnectChan := make(chan struct{})


? ? // next, wrap calls to your handlers in a closure `https://gobyexample.com/closures`

? ? // that captures a reference to the channel you care about

? ? OnConnectErrorHandler := func(err error, socket gowebsocket.Socket) {

? ? ? ? MyOnConnectErrorHandler(connectErrorChan, err, socket)

? ? }

? ? OnDisconnectedHandler := func(err error, socket gowebsocket.Socket) {

? ? ? ? MyOnDisconectedHandler(surpriseDisconnectChan, err, socket)

? ? }

? ? // ... declare any other handlers that might close the connection here


? ? // Do your setup logic here

? ? // serviceURL, e := GetContext().getServiceURL(appName)

? ? // . . .

? ? // socket := gowebsocket.New(url)


? ? socket.OnConnectError = OnConnectErrorHandler

? ? socket.OnConnected = OnConnectedHandler

? ? socket.OnTextMessage = socketTextMessageHandler

? ? socket.OnDisconnected = OnDisconnectedHandler


? ? // Prepare and send your message here...

? ? // LogDebug("In %v func connecting to URL? %v", methodName, url)

? ? // . . .

? ? // socket.SendText(jsonStr)


? ? // now wait for one of your signalling channels to close.

? ? select { // this will block until one of the handlers signals an exit

? ? case <-connectError:

? ? ? ? err = errors.New("never connected? :( ")

? ? case <-successDone:

? ? ? ? socket.Close()

? ? ? ? LogDebug("mission accomplished! :) ")

? ? case <-surpriseDisconnect:

? ? ? ? err = errors.New("somebody cut the wires!? :O ")

? ? }


? ? if err != nil {

? ? ? ? LogDebug(err)

? ? }

? ? return err

}


// *Your* connect error handler will take an extra channel as a parameter

func MyOnConnectErrorHandler(done chan struct{}, err error, socket gowebsocket.Socket) {

? ? methodName := "OnConnectErrorHandler"

? ? LogDebug("Starting %v parameters [err = %v , socket = %v]", methodName, err, socket)

? ? LogInfo("Disconnected from server ")

? ? close(done) // signal we are done.

}

這有幾個優點:


1)你不需要猜測哪些回調發生在進程中,哪些回調發生在后臺 goroutine 中(并且你不必讓所有通道都緩沖“以防萬一”)


2) 在多個通道上進行選擇可以讓您找出退出的原因,并可能以不同的方式處理清理或日志記錄。


注意 1:如果您選擇使用close信令,則必須為每個源使用不同的通道,以避免可能導致通道從不同的 goroutine 關閉兩次的競爭條件(例如,當您返回響應時會發生超時,并且兩個處理程序都會觸發;關閉同一通道的第二個處理程序會導致panic。)這也是您不希望將defer close所有通道都放在函數頂部的原因。


注意2:與您的問題沒有直接關系,但是 - 您不需要關閉每個通道 - 一旦它的所有句柄超出范圍,無論通道是否已關閉,它都會被垃圾收集。


查看完整回答
反對 回復 2023-06-26
  • 2 回答
  • 0 關注
  • 161 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號