2.3.2 init関数を使うべき場合
init()関数使用が不適切な場合
code:go
package main
import (
"database/sql"
"log"
"os"
)
var db *sql.DB
func init() {
dataSourceName := os.Getenv("MYSQL_DATA_SOURCE_NAME")
d, err := sql.Open("mysql", dataSourceName)
if err != nil {
log.Panic(err)
}
err = d.Ping()
if err != nil {
log.Panic(err)
}
db = d
}
上記のinit()関数は下記の問題を抱えている
呼び出し元でエラーハンドリング出来ない
init()関数はエラーを返さないので、エラーを通知するにはpanicを起こすしかなくなる
接続失敗時のリトライやフォールバックをする余地がなくなってしまう
テストしづらくなる
DB接続が必要のない単体テストを追加する場合、init()関数によって不必要なDB接続が必要になり、単体テスト実装を複雑化してしまう
グローバル変数にコネクションプールを代入
どの関数でもグローバル変数を変更できる
グローバル関数に依存する関数を切り離せないので、単体テストが複雑になる可能性がある
問題の解決
code:go
package main
import (
"database/sql"
)
func createClient(dataSourceName string) (*sql.DB, error) {
db, err := sql.Open("mysql", dataSourceName)
if err != nil {
return nil, err
}
if err = db.Ping(); err != nil {
return nil, err
}
return db, nil
}
改善点
テストが書きやすくなる
コネクションプールは、関数内にカプセル化される
呼び出し元でエラーハンドリングできる