こんにちは。よっしーです(^^)
今日は、Golangにおけるデータベース接続についてご紹介します。
概要
本記事では、Goとその標準ライブラリのdatabase/sqlパッケージを使ってリレーショナルデータベースにアクセスするための基本をご紹介します。
Goとそのツールに基本的な知識があれば、このチュートリアルを最大限に活用することができます。
使用するdatabase/sqlパッケージには、データベースへの接続、トランザクションの実行、進行中の操作のキャンセルなどのための型と関数が含まれています。
パッケージの使用方法の詳細については、下記の「データベースへのアクセス」を参照してください。
この記事では、データベースを作成し、そのデータベースにアクセスするためのコードを記述します。サンプルプロジェクトは、ビンテージジャズのレコードに関するデータのリポジトリです。
下記のセクションで進めていきます。
- コード用のフォルダを作成する。
- データベースをセットアップする。
- データベースドライバーをインポートします。
- データベースハンドルを取得し、接続します。
- 複数行のクエリを実行する。
- 1行のクエリを実行する
- データを追加する。
本記事では、4のセクションまでを説明しています。5以降のセクションは次回の記事でご紹介します。
コード用のフォルダを作成する
最初に作業ディレクトリを作成します。手順は下記のコマンドになります。
mkdir 13_learn-golang-database-access
cd 13_learn-golang-database-access
asdfコマンドで使用するGolangのバージョンを指定します。すでにGolangが実行できる状態にある方は、このコマンドをスキップしても問題ありませんが、Go 1.18以降である必要があります。
asdf local golang 1.20.5
モジュールの初期化を初期化します。この例では、data-accessモジュールを作成します。
mkdir data-access
cd data-access
go mod init example/data-access
データベースをセットアップする
データベースはdockerを利用して、セットアップします。
MySQLのバージョンを設定します。MySQLクライアントとして使用します。
cd ../
asdf local mysql 5.7.31
データベース用の作業ディレクトリを作成します。
mkdir database
cd database
必要なファイルを作成します。
touch compose.yml
touch my.cnf
mkdir database/init_scripts
touch init_scripts/v0.0.1__create_table.sql
touch init_scripts/v0.0.2__insert.sql
compose.ymlファイルを下記の内容で保存します。
version: '3'
services:
mysql:
image: mysql:5.7
platform: linux/amd64
ports:
- 3306:3306
volumes:
- ./my.cnf:/etc/mysql/conf.d/my.cnf
- ./init_scripts:/docker-entrypoint-initdb.d
environment:
- MYSQL_ROOT_PASSWORD=P@ssw0rd
- MYSQL_DATABASE=recordings
- TZ=Asia/Tokyo
my.cnfファイルを下記の内容で保存します。
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqldump]
default-character-set=utf8
[mysqld]
character-set-server=utf8
log_output = FILE
general_log_file = /var/log/mysql/mysql.log
general_log = 1
v0.0.1__create_table.sqlファイルを下記の内容で保存します。
CREATE TABLE album (
id INT AUTO_INCREMENT NOT NULL,
title VARCHAR(128) NOT NULL,
artist VARCHAR(255) NOT NULL,
price DECIMAL(5,2) NOT NULL,
PRIMARY KEY (`id`)
);
v0.0.2__insert.sqlファイルを下記の内容で保存します。
INSERT INTO album
(title, artist, price)
VALUES
('Blue Train', 'John Coltrane', 56.99),
('Giant Steps', 'John Coltrane', 63.99),
('Jeru', 'Gerry Mulligan', 17.99),
('Sarah Vaughan', 'Sarah Vaughan', 34.98);
mysqlを起動します。
docker compose up -d
コマンドラインで、MySQLのDBMSにログインします。
mysql -uroot -p -h 127.0.0.1
DBMSのコマンドプロンプトで、SELECT文を使用して、データ付きテーブルが正常に作成されたことを確認します。
use recordings;
select * from album;
データベースドライバーをインポートします。
データベースといくつかのデータを手に入れたら、Goのコードを書き始めましょう。
データベースドライバを探し、インポートします。このドライバは、database/sqlパッケージの関数を通して行う要求を、データベースが理解できる要求に変換します。
ブラウザで SQLDrivers wiki ページにアクセスし、使用できるドライバを特定します。
このページのリストを使用して、使用するドライバを特定します。MySQLにアクセスするには、Go-MySQL-Driverを使用します。
ドライバのパッケージ名(ここではgithub.com/go-sql-driver/mysql)に注意してください。
テキストエディタを使用して、Goコードを記述するファイルを作成し、先ほど作成したdata-accessディレクトリにmain.goとして保存します。
cd ../
touch data-access/main.go
main.goの中に、以下のコードを貼り付けて、ドライバパッケージをインポートします。
package main
import "github.com/go-sql-driver/mysql"
データベースハンドルを取得し、接続します。
データベースハンドルでデータベースにアクセスするGoコードを書いてみましょう。
特定のデータベースへのアクセスを表すsql.DB構造体へのポインタを使用することになります。
main.goの、先ほど追加したimportコードの下に、データベースハンドルを作成するための以下のGoコードを貼り付けます。
var db *sql.DB
func main() {
// Capture connection properties.
cfg := mysql.Config{
User: os.Getenv("DBUSER"),
Passwd: os.Getenv("DBPASS"),
Net: "tcp",
Addr: "127.0.0.1:3306",
DBName: "recordings",
AllowNativePasswords: true,
}
// Get a database handle.
var err error
db, err = sql.Open("mysql", cfg.FormatDSN())
if err != nil {
log.Fatal(err)
}
pingErr := db.Ping()
if pingErr != nil {
log.Fatal(pingErr)
}
fmt.Println("Connected!")
}
main.goファイルの先頭、パッケージ宣言のすぐ下に、今書いたコードをサポートするために必要なパッケージをインポートしてください。
これで、ファイルの先頭は次のようになります:
package main
import (
"database/sql"
"fmt"
"log"
"os"
"github.com/go-sql-driver/mysql"
)
MySQL ドライバモジュールを依存関係として追跡を開始する。
go getを使って、github.com/go-sql-driver/mysqlモジュールを自分のモジュールの依存関係として追加してください。”現在のディレクトリにあるコードの依存関係を取得する “という意味で、ドット引数を使用します。
go get .
今回は、下記のモジュールが追加されました。
go: downloading github.com/go-sql-driver/mysql v1.7.1
go: added github.com/go-sql-driver/mysql v1.7.1
Goがこの依存関係をダウンロードしたのは、前のステップでimport宣言に追加したからです。依存関係の追跡の詳細については、依存関係の追加を参照してください。
コマンドプロンプトから、Goプログラムが使用するDBUSERとDBPASSの環境変数を設定します。
export DBUSER=root
export DBPASS=P@ssw0rd
main.goのあるディレクトリのコマンドラインから、”カレントディレクトリのパッケージを実行する “という意味で、ドット引数をつけてgo runと入力し、コードを実行する。
go run .
下記のような結果になれば成功です。
% go run .
Connected!
解説
main.go
package main
import (
"database/sql"
"fmt"
"log"
"os"
"github.com/go-sql-driver/mysql"
)
var db *sql.DB
func main() {
// Capture connection properties.
cfg := mysql.Config{
User: os.Getenv("DBUSER"),
Passwd: os.Getenv("DBPASS"),
Net: "tcp",
Addr: "127.0.0.1:3306",
DBName: "recordings",
AllowNativePasswords: true,
}
// Get a database handle.
var err error
db, err = sql.Open("mysql", cfg.FormatDSN())
if err != nil {
log.Fatal(err)
}
pingErr := db.Ping()
if pingErr != nil {
log.Fatal(pingErr)
}
fmt.Println("Connected!")
}
このコードは、Go言語を使用してMySQLデータベースに接続するためのプログラムです。以下にコードの詳細な解説を示します。
- パッケージのインポート:
import (
"database/sql"
"fmt"
"log"
"os"
"github.com/go-sql-driver/mysql"
)
必要なパッケージをインポートしています。database/sql
はデータベース操作のためのパッケージであり、github.com/go-sql-driver/mysql
はGo言語のMySQLドライバです。
変数の宣言:
var db *sql.DB
db
はデータベースのハンドルを保持するための変数です。
main
関数:
func main() {
// Capture connection properties.
cfg := mysql.Config{
User: os.Getenv("DBUSER"),
Passwd: os.Getenv("DBPASS"),
Net: "tcp",
Addr: "127.0.0.1:3306",
DBName: "recordings",
AllowNativePasswords: true,
}
// Get a database handle.
var err error
db, err = sql.Open("mysql", cfg.FormatDSN())
if err != nil {
log.Fatal(err)
}
pingErr := db.Ping()
if pingErr != nil {
log.Fatal(pingErr)
}
fmt.Println("Connected!")
}
main
関数はプログラムのエントリーポイントです。
まず、mysql.Config
構造体を使って接続の設定情報をキャプチャします。
User
とPasswd
は環境変数から取得し、Net
は通信プロトコルを指定し、Addr
は接続先のIPアドレスとポート番号、DBName
は接続するデータベースの名前です。
また、AllowNativePasswords
をtrue
に設定してネイティブパスワード認証を有効にします。
次に、sql.Open
関数を使ってデータベースハンドルを取得します。"mysql"
は使用するドライバ名です。
cfg.FormatDSN()
はMySQL接続文字列を生成するメソッドです。
接続に失敗した場合は、エラーログを出力してプログラムを終了します。
db.Ping()
を使ってデータベースへの接続を確認します。
接続に失敗した場合もエラーログを出力してプログラムを終了します。
最後に、接続が成功したことを示すメッセージを出力します。
このコードは、指定された接続情報を使ってMySQLデータベースに接続し、接続が成功したかどうかを確認するためのプログラムです。もし接続に成功すれば、「Connected!」というメッセージが表示されます。
おわりに
今日は、Golangにおけるデータベース接続についてご紹介しました。
次回は、次のセクションのご紹介をします。
- 複数行のクエリを実行する。
- 1行のクエリを実行する
- データを追加する。
本記事で使用したコードは下記のリポジトリにあります。
何か質問や相談があれば、遠慮なくコメントしてください。また、エンジニア案件についても、いつでも相談にのっていますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント