これから新規に書くコードでは mysql.NewConnector と sql.OpenDBを使ったほうが良さそう、という話。
昔からある書き方
go-sql-driver/mysql のDSNを文字列結合で実現するのは意外と大変なので、 某所ではDSN(Data Source Name)の生成を mysql.Config を使って行っています。
// DSNの生成
cfg := mysql.NewConfig()
cfg.User = "user"
cfg.Passwd = "password"
cfg.DBName = "dbname"
dsn := cfg.FormatDSN()
// 接続
db, err := sql.Open("mysql", dsn)
if err != nil {
panic(err)
}
新しい書き方
実はDSNを生成しなくとも、 mysql.Configから *sql.DB を取得できます。
cfg := mysql.NewConfig()
cfg.User = "user"
cfg.Passwd = "password"
cfg.DBName = "dbname"
// *mysql.Config を直接渡す
conn, err := mysql.NewConnector(cfg)
if err != nil {
panic(err)
}
db := sql.OpenDB(conn)
なぜ新しい書き方を勧めるのか
mysql.Config には文字列にシリアライズできないフィールドが存在するからです。 そのためDSNに変換したときに、情報のロスが起こります。
たとえば先日 BeforeConnect
オプションの紹介をしました。
しかしこのオプションはDSNでは表現できません。
BeforeConnect
オプションにはGoの関数を指定するのですが、Goの関数は文字列にシリアライズすることができないからです。
そのため「古い書き方」ではうまく動作せず、「新しい書き方」のみで意図した挙動となります。
まとめ
以下の書き方を使いましょう。
cfg := mysql.NewConfig()
cfg.User = "user"
cfg.Passwd = "password"
cfg.DBName = "dbname"
// *mysql.Config を直接渡す
conn, err := mysql.NewConnector(cfg)
if err != nil {
panic(err)
}
db := sql.OpenDB(conn)