GoでMySQLやMariaDBのtimestampを読みこむ:データベース接続時に?parseTime=trueを指定する

Go でデータベースに接続するときは go-sql-driver/mysql などのドライバーを使う。接続する関数は次のようになる。

package utils

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"time"
)

func Connect(database string) *sql.DB {
	user := "root"
	pass := "pass"
	proto := "tcp(localhost:3306)"
	s := user + ":" + pass + "@" + proto + "/" + database + "?parseTime=true"
	db, err := sql.Open("mysql", s)
	if err != nil {
		fmt.Println(err)
	}
	db.SetConnMaxLifetime(time.Second * 5)
	return db
}

上の

s := user + ":" + pass + "@" + proto + "/" + database + "?parseTime=true"

という部分を見ると?の後に parseTime=true があります。これが日時をパースするためのコツ。これをつけると下のコードがうまく動く。

db := utils.Connect("post_db")
query := "select title, description, date_created from post"
stmt, e := db.Prepare(query)
if e != nil {
	return
}
rows, e := stmt.Query(id)
if e != nil {
	return
}
for rows.Next() {
	e = rows.Scan(&post.Title, &post.Description, &post.DateCreated)
}

post.DateCreated という部分に注目。この date_created というカラムは timestamp 型です。もし

s := user + ":" + pass + "@" + proto + "/" + database

としたら、つまり ?parseTime=true をつけなかったらどうなるか。おそらく Scan して post.DateCreated に読みこんだ値は 0 です。これを回避するために

s := user + ":" + pass + "@" + proto + "/" + database + "?parseTime=true"

とする。すると

2019-06-28 15:45:44 +0000 UTC

といった日時が post.DateCreated に入る。