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

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

為什么我在main中使用goroutine時我的程序沒有關閉?

為什么我在main中使用goroutine時我的程序沒有關閉?

Go
GCT1015 2023-01-03 17:17:07
語境請仔細閱讀代碼中的注釋。一切都在他們身上。如果您有使用經驗discordgo完整的代碼可以在這里找到:https ://github.com/telephrag/kubinka/tree/bug (查看包strg和main)添加 goroutine 命令處理程序也會停止正常工作。與數據庫交互相關的所有內容(分別在 /deploy 和 /return 上存儲和從數據庫中刪除)根本不起作用。用戶只會收到“應用程序未響應”消息而不是正確的響應(請參閱以cmd_前綴開頭的包)。package mainimport (    "context"    "fmt"    "log"    "os"    "os/signal"    "syscall"    "time"    "go.etcd.io/bbolt")/*  TO REPRODUCE:Start the program wait a few seconds and press ^C.Expect the case of program not shutting down after few attempts.*/func WatchExpirations(ctx context.Context, db *bbolt.DB, bkt string) error {    timeout := time.After(time.Second * 5)    for {        select {        case <-timeout:            tx, err := db.Begin(true)            if err != nil {                return fmt.Errorf("bolt: failed to start transaction")            }            bkt := tx.Bucket([]byte(bkt))            c := bkt.Cursor()            for k, v := c.First(); k != nil; k, v = c.Next() {                // do stuff with bucket...                fmt.Println(v) // check if v matches condition, delete if does                if err := tx.Commit(); err != nil { // BUG: commiting transaction in a loop                    tx.Rollback()                    return fmt.Errorf("bolt: failed to commit transaction: %w", err)                }                timeout = time.After(time.Second * 5)            }        case <-ctx.Done():            return ctx.Err()        }    }}func main() {    ctx, cancel := context.WithCancel(context.Background())    db, err := bbolt.Open("kubinka.db", 0666, nil)    if err != nil {        log.Panicf("failed to open db %s: %v", "kubinka.db", err)    }    if err = db.Update(func(tx *bbolt.Tx) error {        _, err := tx.CreateBucketIfNotExists([]byte("players"))        if err != nil {            return fmt.Errorf("failed to create bucket %s: %w", "players", err)        }        return nil    }); err != nil {        log.Panic(err)    }
查看完整描述

1 回答

?
慕仙森

TA貢獻1827條經驗 獲得超8個贊

根據您的回購協議中的評論,問題似乎出在這里:

tx, err := db.Begin(true)

if err != nil {

   return fmt.Errorf("bolt: failed to start transaction")

}

bkt := tx.Bucket([]byte(bkt))

c := bkt.Cursor()

for k, v := c.First(); k != nil; k, v = c.Next() {

    // do stuff with bucket...

    fmt.Println(v) // check if v matches condition, delete if does


    if err := tx.Commit(); err != nil { // BUG: commiting transaction in a loop

        tx.Rollback()

        return fmt.Errorf("bolt: failed to commit transaction: %w", err)

    }

    timeout = time.After(time.Second * 5)

}

循環可以迭代 0 次。

  • 如果沒有迭代 -tx不提交timeout也不重置(因此case <-timeout:不會再次觸發)。

  • 如果有多次迭代 - 您將嘗試tx.Commit()多次(錯誤)。

這可能導致了您看到的問題;bolt Close功能:_

關閉釋放所有數據庫資源。在關閉數據庫之前必須關閉所有事務。

因此,如果有一個事務運行Close塊直到完成(內部螺栓在事務開始時鎖定互斥鎖并在完成時釋放它)。

解決方案是確保事務始終關閉(并且只關閉一次)。



查看完整回答
反對 回復 2023-01-03
  • 1 回答
  • 0 關注
  • 102 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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