为了账号安全,请及时绑定邮箱和手机立即绑定

无法识别同步中的错误。一旦使用

无法识别同步中的错误。一旦使用

Go
小唯快跑啊 2022-12-05 11:11:45
我正在做一个关于 Golang 的在线课程。以下代码片段作为滥用 的示例出现在课程材料中sync.Once:var (    once sync.Once    db   *sql.DB)func DbOnce() (*sql.DB, error) {    var err error    once.Do(func() {        fmt.Println("Am called")        db, err = sql.Open("mysql", "root:test@tcp(127.0.0.1:3306)/test")        if err != nil {            return        }        err = db.Ping()    })    if err != nil {        return nil, err    }    return db, nil}据推测,以上是 SQL 连接管理器的错误实现。我们,学生,要自己找出错误,我正在努力解决这个问题。代码即使并行运行也能正常运行。这就是我使用它的方式:func main() {    wg := sync.WaitGroup{}    wg.Add(10)    for i := 0; i < 10; i++ {        go (func() {            db, err := DbOnce()            if err != nil {                panic(err)            }            var v int            r := db.QueryRow("SELECT 1")            err = r.Scan(&v)            fmt.Println(v, err)            wg.Done()        })()    }    wg.Wait()}我知道这里不鼓励家庭作业问题,所以我不要求一个完整的解决方案,只是一个提示就可以了。错误是否与并发有关(即我需要在特定的并发上下文中运行它)?是 sql.Open 的具体用法吗?
查看完整描述

1 回答

?
蓝山帝景

TA贡献1843条经验 获得超7个赞

db变量的初始化是可以的。问题在于返回的错误。


如果您DbOnce()是第一次调用并且打开数据库连接失败,则会正确返回该错误。但是后续调用呢?db初始化代码不会再次运行,因此可能nil db会返回,并且由于未运行初始化代码,因此会返回err变量的默认值,即nil. 综上所述,初始化错误丢失,不再报错。


一种解决方案是在连接失败时停止应用程序(在第一次调用时)。另一种选择是将初始化错误与 一起存储在包级变量中db,并从中返回DbOnce()(而不是为此使用局部变量)。前者的优点是您不必处理从DbOnce()返回的错误,因为它甚至不必返回错误(如果出现错误,您的应用程序将终止)。


后者可能看起来像这样:


var (

    once  sync.Once

    db    *sql.DB

    dbErr error

)


func DbOnce() (*sql.DB, error) {

    once.Do(func() {

        fmt.Println("Am called")

        db, dbErr = sql.Open("mysql", "root:test@tcp(127.0.0.1:3306)/test")

        if dbErr != nil {

            return

        }

        dbErr = db.Ping()

    })

    return db, dbErr

}


查看完整回答
反对 回复 2022-12-05
  • 1 回答
  • 0 关注
  • 81 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号