複数の関数で、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()の返り値を格納したものではないからです。