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

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

Go:負的 WaitGroup 計數器

Go:負的 WaitGroup 計數器

Go
慕斯王 2022-10-17 16:44:54
我有點陌生,正在修改我在其他地方找到的代碼以滿足我的需求。正因為如此,我并不完全理解這里發生了什么,盡管我明白了一般的想法。我正在使用 go 例程運行一些 websocket 客戶端,但是我遇到了一個導致程序崩潰的意外錯誤。當從 websocket 讀取消息時出錯(檢查 readHandler 函數中的 conn.ReadMessage() 函數),我的程序似乎關閉了太多線程(如果這是錯誤的術語,請原諒)。關于如何解決這個問題的任何想法?我非常感謝任何花時間瀏覽它的人。提前致謝!package mainimport (    "context"    "fmt"    "os"    "time"    "os/signal"    "syscall"    "sync"    "net/url"    "github.com/gorilla/websocket"    "strconv"    "encoding/json"    "log"    "bytes"    "compress/gzip"    "io/ioutil")// Structstype Ping struct {    Ping    int64   `json:"ping"`}type Pong struct {    Pong        int64       `json:"pong"`}type SubParams struct {    Sub         string          `json:"sub"`    ID          string          `json:"id"`}func InitSub(subType string, pair string, i int) []byte {    var idInt string = "id" + strconv.Itoa(i)    subStr := "market." + pair + "." + subType    sub := &SubParams{        Sub: subStr,        ID: idInt,    }    out, err := json.MarshalIndent(sub, "", " ")    if err != nil {        log.Println(err);    }    //log.Println(string(out))    return out}// main funcfunc main() {    var server string = "api.huobi.pro"    pairs := []string{"btcusdt", "ethusdt", "ltcusdt"}    comms := make(chan os.Signal, 1)    signal.Notify(comms, os.Interrupt, syscall.SIGTERM)    ctx := context.Background()    ctx, cancel := context.WithCancel(ctx)    var wg sync.WaitGroup    for x, pair := range pairs {        wg.Add(1)        go control(server, "ws", pair, ctx, &wg, x+1)    }    <-comms    cancel()    wg.Wait()}func control(server string, path string, pair string, ctx context.Context, wg *sync.WaitGroup, i int) {    fmt.Printf("Started control for %s\n", server)    url := url.URL {        Scheme: "wss",        Host: server,        Path: path,    }    fmt.Println(url.String())    conn, _, err := websocket.DefaultDialer.Dial(url.String(), nil)    if err != nil {        panic(err)    }}
查看完整描述

1 回答

?
回首憶惘然

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

readHandler連接失敗時跳出循環:


  _, p, err :=  conn.ReadMessage()

  if err != nil {

      wg.Done()

      fmt.Println(err)

      return // <--- add this line

  }

如果沒有返回,函數會在一個緊密的循環中旋轉,讀取錯誤,直到出現恐慌。


在 goroutine 的開頭使用defer wg.Done()以確保 Done 只被調用一次。


func readHandler(ctx context.Context, conn *websocket.Conn, wg *sync.WaitGroup, server string) {

    defer wg.Done()

    for {

      select {

      case <-ctx.Done():

          return

      default:

          _, p, err := conn.ReadMessage()

          if err != nil {

              fmt.Println(err)

              return

          }

     ...

也更新control功能。


因為調用者不會與 并發執行任何代碼,所以運行goroutinereadHander沒有任何價值。readHandler刪除所有對等待組的引用readHandler并直接調用該函數:更改go readHandler(ctx, conn, &localwg, server)為readHandler(ctx, conn, server).


還有更多問題,但這應該會讓你走得更遠。


查看完整回答
反對 回復 2022-10-17
  • 1 回答
  • 0 關注
  • 119 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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