Go database/sql チュートリアル 03 - データベースへのアクセス

"Accessing the Database" from database/sql tutorial

Go database/sqlチュートリアルのデータベースへのアクセスの日本語意訳になります。


データベースへのアクセス

ドライバパッケージのロードをしたので、sql.DBというデータベースオブジェクトを作る準備ができました。

sql.DBを作るには、sql.Open()を使います。
この関数は *sql.DB を返却します。

func main() {
	db, err := sql.Open("mysql",
		"user:password@tcp(127.0.0.1:3306)/hello")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
}

この例で、いくつかの事柄を説明していきます。

  • sql.Openの第一引数はドライバ名です。これはドライバがdatabase/sqlに対して登録した文字列で、通常は混乱を避けるためにパッケージ名と同じ文字列になっています。例えば、github.com/go-sql-driver/mysqlドライバではmysqlとなります。いくつかのドライバはこの慣例に従っていません。(例: sqlite3用のgithub.com/mattn/go-sqlite3postgres用のgithub.com/lib/pq
  • 第二引数は各ドライバ向けのシンタックスになっていて、実際のデータストアへのアクセス方法をドライバに指示します。この例では、ローカルのMySQLサーバインスタンス内の「hello」データベースに接続しています。
  • database/sqlの操作による全てのエラーは(ほぼ)常にチェックし、処理する必要があります。エラーチェックが意味をなさない特別なケースがいくつかありますが、それについては後ほど説明します。
  • defer db.Cloese() というイディオムは sql.DBが関数のスコープを超えないようにするために使われます。

みなさんの直感に反しているかもしれませんが、sql.Open()はデータベースへの接続を確立しませんし、ドライバの接続パラメータの検証もしません。
その代わりに、後で使用される抽象化されたデータベースの準備をするだけです。
実データストアへの実際のコネクションは、必要になった時に初めて、遅延して確立されるでしょう。
データベースが利用可能でアクセス可能かどうか、すぐに確認したい場合はdb.Ping()を使ってください。(例えば、ネットワーク接続ができログイン可能かどうかチェックする場合)
その際はエラーチェックを忘れないでください。

err = db.Ping()
if err != nil {
	// ここでエラー処理をする
}

作業終了後には、データーベースを Close()するのが普通ですが、sql.DBオブジェクトは長期間使われるように設計されています。Open()Close()を頻繁に行わないでください。
その代わりに、それぞれのデータストアごとに単一のsql.DBオブジェクトを作り、プログラムのアクセスが終わるまで保持してください。
必要に応じてそのsql.DBを引き回すか、あるいはどうにかグローバルに利用可能にできるようにしてください。ただしClose()せずに開いたままにしておいてください。
そして一時的な関数でOpen()Close()をしてはいけません。
代わりに、その一時的な関数へ引数として渡すようにしましょう。

もしもsql.DBを長期間存在するオブジェクトとして扱わないとすると、不十分な再利用やコネクション共有、ネットワークリソースの枯渇、またはTIME_WAITステータスで残り続ける大量のTCPコネクションによる散発的な障害といった問題が発生する可能性があります。
このような問題は、database/sqlが設計通りにきちんと使われていないというサインです。

それでは今度はsql.DBオブジェクトを使ってみましょう。


前章: ドライバのインポート
次章: 結果の取得

 
comments powered by Disqus