go 使用 Mysql 包报错: database is closed?

题目描述

使用的go-sql-driver/mysql 驱动,在另一个 package 中初始化连接池对象, 并且将 *sq;.DB 设为全局变量在 另一个包中引用,使用Query 获取 MySQL 连接 ,查询一直报错 ?

相关代码

package database

import (
    "database/sql"

    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "log"
)

var Db *sql.DB

func init() {
    var err error
    Db, err = sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/blog?charset=utf8")
    if err != nil {

        fmt.Println("conn failed!")
        log.Fatal(err.Error())
    }
    defer Db.Close()

    fmt.Println(&Db)

    Db.SetMaxOpenConns(2000)
    Db.SetMaxIdleConns(1000)

    err = Db.Ping()
    if err != nil {
        log.Fatal(err.Error())
    }

    fmt.Println("db inti")
}
package controllers

import (
    . "build-web-application/004-blog/database"
    //"database/sql"
    "fmt"
    "github.com/gin-gonic/gin"
    _ "github.com/go-sql-driver/mysql"
    "log"
)

func GetPosts(c *gin.Context) {

    rows, err := Db.Query(`SELECT * FROM t_post`)
    if err != nil {
        log.Fatal(err)
    }
    //    defer rows.Close()

    for rows.Next() {
        var id int
        var post string
        err = rows.Scan(&id, &post)
        fmt.Println(id)
        fmt.Println(post)

    }

}

阅读 18.1k
3 个回答

@勤奋的小小尘 说的对,你在init()中使用defer Db.Close()的结果是,init函数返回的时候,关闭了数据库连接,而后又在GetPosts()中调用,就会报数据库已关闭的错误。

正确的做法是,在你完全使用完Db后,再进行关闭。我之前写过一篇关于defer的文章,可以看一下:https://segmentfault.com/a/11...

图片描述

看划红线的地方,你已经close了,外面这么可能还能用。。
建议先理解defer的含义。
一定要先看基础,循序渐进,不要急躁

defer Db.Close()
会在init函数结束的时候执行。
所以这种类型的资源是不需要defer关闭的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题