技術向上

プログラミングの学び、気になるテクノロジーやビジネストレンドを発信

MySQL - invalid memory address or nil pointer dereference【Go】

複数の関数で、DBコネクションを使い回す場合には、注意が必要です。
dbだけでなく、sql.Open()の返り値に含まれるerrもpackageグローバルに定義して、
sql.Open()の返り値のアサインは「:=」ではなく、「=」を使用します。

var db *sql.DB

var err error    // *sql.DBだけでなく、errもpackageグローバルに定義する

func main() {
    db, err = sql.Open("mysql", "root:password@/database-name")    // errをグローバルに定義せず、「:=」を使うとinvalidエラーになる
    check(err)
    defer db.Close()
    ...
    http.HandleFunc("/read", read)
    http.Handle("/favicon.ico", http.NotFoundHandler())
    http.ListenAndServe(":8080", nil)
}

func read(w http.ResponseWriter, req *http.Request) {
    rows, err := db.Query(`SELECT name FROM sample;`)    // errをグローバルに定義せずsql.Open()の返り値のアサインに「:=」を使うと、ここでinvalidエラーになる
    check(err)
    defer rows.Close()
    ...
} 


errをグローバルに定義せず、sql.Open()の返り値のアサインを「:=」にすると、
read()のdb.Query()が実行された時、invalid memory address or nil pointer dereferenceエラーが発生します。
dbが新たに作成されて、それはsql.Open()の返り値を格納したものではないからです。

*sql.DB invalid memory address or nil pointer dereference · Issue #150 · go-sql-driver/mysql · GitHub