Go言語でデータベースに接続するための方法について紹介します。
今回はMySQLを利用します。
目次
Go言語でデータベースへ接続する手順
- データベース接続のパッケージをインポート
- 接続するデータベースのドライバをインポート
- データベースのオープン
以下では各手順について紹介します。
データベース接続のパッケージをインポート
データベースに接続するためのパッケージをインポートします。
Go言語の標準パッケージではdatabase/sqlが該当します。
import "database/sql"
接続するデータベースのドライバをインポート
データベースに接続するにはドライバが必要です。ドライバはデータベースの種類ごとに用意されています。
たとえばMySQLの場合はgithub.com/go-sql-driver/mysqlが該当します。
ドライバのパッケージは直接コード上で利用しないのでアンダースコア(_
)でインポートします。(blank identifier)
import _ "github.com/go-sql-driver/mysql"
各種データベースのドライバはこちらで確認ができます。
データベースのオープン
データベースへアクセスするためのオブジェクトを作成します。
database/sql
の場合、Open関数を利用してdb, err := sql.Open("ドライバ名", "接続文字列")
のようにすると変数db
を通じてデータベースへアクセスできます。
"接続文字列"
は各種ドライバのドキュメントを参考に記載します。MySQLの場合はこちらににフォーマットが記載されています。
動作確認
実際にGo言語からデータベースに接続してみます。
下準備: 検証用のデータベースをDockerで用意する
今回はMySQLのDockerイメージを利用して検証用のデータベースを構築します。
- ユーザー名: webuser
- パスワード: webpass
- データベース名: go_mysql8_development
- ポート: 3306
docker-compose.yml
version: '3'
services:
db:
image: mysql:8.0.21
ports:
- '3306:3306'
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_USER: 'webuser'
MYSQL_PASSWORD: 'webpass'
MYSQL_ROOT_PASSWORD: 'pass'
MYSQL_DATABASE: 'go_mysql8_development'
docker-compose.yml
でコンテナ起動後、以下のようにデータベースに接続できればOKです。
### コンテナの起動
$ cd /path/to/docker-compose-file
$ docker-compose up -d
### dbコンテナにアクセスし、データベースがあることを確認
$ docker-compose exec db mysql -uwebuser -pwebpass -D go_mysql8_development -e "show databases"
+-----------------------+
| Database |
+-----------------------+
| go_mysql8_development |
| information_schema |
+-----------------------+
サンプルコードの実装と実行
最終的なサンプルコードは以下のようになります。
sql.Open
はあくまでデータベースへ接続するオブジェクトを生成しているだけです。
ですので、実際のデータベースへの接続テストはdb.Ping()
で確認します。
main.go
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
// [ユーザ名]:[パスワード]@tcp([ホスト名]:[ポート番号])/[データベース名]?charset=[文字コード]
dbconf := "webuser:webpass@tcp(127.0.0.1:3306)/go_mysql8_development?charset=utf8mb4"
db, err := sql.Open("mysql", dbconf)
// 接続が終了したらクローズする
defer db.Close()
if err != nil {
fmt.Println(err.Error())
}
err = db.Ping()
if err != nil {
fmt.Println("データベース接続失敗")
return
} else {
fmt.Println("データベース接続成功")
}
}
サンプルコードを実行し、以下のように『データベース接続成功』の文字列が表示されればOKです。
### 作業ディレクトリへ移動
$ cd /path/to/project
### パッケージのインストール
$ go mod init example
$ go mod tidy
### 実行
$ go run main.go
データベース接続成功
参考: データベース接続のソースコードをリファクタリングする
上記で紹介したソースコードは以下の改善点があります。
- データベース接続のロジックがmain関数に直接書かれている
- データベース情報がソースコードにベタ書きされている
ここからはソースコードのリファクタリング方法について紹介します。
データベース接続のロジックを別パッケージ化する
データベース接続のロジックを別パッケージにすることでmain関数をシンプルにします。
main.go
package main
import (
+ "example/database" // "モジュール名/パッケージ名"
"fmt"
- "database/sql"
- _ "github.com/go-sql-driver/mysql"
)
func main() {
+ db := database.Connect()
- dbconf := "webuser:webpass@tcp(127.0.0.1:3306)/go_mysql8_development?charset=utf8mb4"
-
- db, err := sql.Open("mysql", dbconf)
- if err != nil {
- fmt.Println(err.Error())
- }
defer db.Close()
err := db.Ping()
if err != nil {
fmt.Println("データベース接続失敗")
return
} else {
fmt.Println("データベース接続成功")
}
}
データベース接続に関するパッケージは以下の通りです。
外部パッケージから呼び出せるようにするため、関数名は大文字から始めます。
database/connect.go
package database
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func Connect() *sql.DB {
user := "webuser"
password := "webpass"
host := "localhost"
port := "3306"
database_name := "go_mysql8_development"
dbconf := user + ":" + password + "@tcp(" + host + ":" + port + ")/" + database_name + "?charset=utf8mb4"
db, err := sql.Open("mysql", dbconf)
if err != nil {
fmt.Println(err.Error())
}
return db
}
GoDotEnvを導入してデータベース接続情報を.envファイルに配置する
GoDotEnvはGo言語で.envファイルを利用できるようにするパッケージです。
GoDotEnvを利用することでデータベース接続情報を環境変数に置き換えられます。
GoDotEnvはgodotenv.Load()
で環境変数をロードし、os.Getenv("Key名")
で値を呼び出します。
GoDotEnvを利用したdatabase
パッケージのソースコードは以下の通りです。
.env
DB_USER=webuser
DB_PASSWORD=webpass
DB_HOST=db
DB_PORT=3306
DB_DATABASE_NAME=go_mysql8_development
database/connect.go
package database
import (
"database/sql"
"fmt"
"os"
"github.com/joho/godotenv"
_ "github.com/go-sql-driver/mysql"
)
func Connect() *sql.DB {
err := godotenv.Load()
if err != nil {
fmt.Println(err.Error())
}
user := os.Getenv("DB_USER")
password := os.Getenv("DB_PASSWORD")
host := os.Getenv("DB_HOST")
port := os.Getenv("DB_PORT")
database_name := os.Getenv("DB_DATABASE_NAME")
dbconf := user + ":" + password + "@tcp(" + host + ":" + port + ")/" + database_name + "?charset=utf8mb4"
db, err := sql.Open("mysql", dbconf)
if err != nil {
fmt.Println(err.Error())
}
return db
}
最終的なソースコード
リファクタリングを終えた最終的なソースコードは以下の通りです。
main.go
package main
import (
"example/database"
"fmt"
)
func main() {
db := database.Connect()
defer db.Close()
err := db.Ping()
if err != nil {
fmt.Println("データベース接続失敗")
return
} else {
fmt.Println("データベース接続成功")
}
}
database/connect.go
package database
import (
"database/sql"
"fmt"
"os"
"github.com/joho/godotenv"
_ "github.com/go-sql-driver/mysql"
)
func Connect() *sql.DB {
err := godotenv.Load()
if err != nil {
fmt.Println(err.Error())
}
user := os.Getenv("DB_USER")
password := os.Getenv("DB_PASSWORD")
host := os.Getenv("DB_HOST")
port := os.Getenv("DB_PORT")
database_name := os.Getenv("DB_DATABASE_NAME")
dbconf := user + ":" + password + "@tcp(" + host + ":" + port + ")/" + database_name + "?charset=utf8mb4"
db, err := sql.Open("mysql", dbconf)
if err != nil {
fmt.Println(err.Error())
}
return db
}
.env
DB_USER=webuser
DB_PASSWORD=webpass
DB_HOST=db
DB_PORT=3306
DB_DATABASE_NAME=go_mysql8_development
まとめ
- データベース接続のパッケージをインポート
- 接続するデータベースのドライバをインポート
- データベース接続情報をドライバのパラメータに渡す
- データベースをオープンし、オブジェクトを生成
- オブジェクトを通じてデータベースを操作する
Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!