Shogo's Blog

Mar 12, 2024 - 1 minute read - mysql go golang

GoのMySQLドライバーを使うときはmysql.NewConnectorとsql.OpenDBを使おう

これから新規に書くコードでは mysql.NewConnectorsql.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)

参考