My External Storage

May 19, 2019 - 4 minute read - Comments - go sql presentation

[補足資料] Go Conference 2019 Springでdatabase/sql入門を発表した #gocon

Go Conference(GoCon)で「database/sql入門」というタイトルで発表してきた。 この記事は資料中のリンクや、口頭で説明した内容の補足資料となる。

発表資料

サンプルコードは以下になる。

database/sql入門 | 2019 Spring Sessions

データベースサーバについて

DockerHubを使えば使い捨てのRDSをすぐ起動することができる。 DockerHubを見れば公式イメージがある。

マイグレーションツールについて

sql-migrateを推した。

リポジトリパターンについて

設計パターンとして、DBをあつかうときに大抵は選択するであろうリポジトリパターンを紹介した。 pospomeさんがBOOTHで販売しているpospomeのサーバサイドアーキテクチャにGoで書かれた「第4章 詳解リポジトリパターン」という章があるのでそちらを読むと良い(その前の章のアーキテクチャ設計に関する部分も大変参考になる)。

ORMについて

ORMについてはizuminさんらが比較記事を書かれているのでそちらを読んでるとよい。

database/sqlパッケージの使い方について

GoDocをみるのが一番よい。

たとえば、sql.Open関数は一度だけ呼び出せばよい、など、GoDocを見ると使用上の注意がしっかり書かれている。

The returned DB is safe for concurrent use by multiple goroutines and maintains its own pool of idle connections. Thus, the Open function should be called just once. It is rarely necessary to close a DB.

ざっくりサマリを読みたいときはGo Wikiに記事がある。

GoDocサーバの裏でDBは動いていないので実行してもエラーになってしまうが、Examplesにサンプルコードが大量にあるのでそちらを参考にできる。

// https://golang.org/pkg/database/sql/#example_DB_QueryContext

package main

import (
	"context"
	"database/sql"
	"fmt"
	"log"
	"strings"
)

var (
	ctx context.Context
	db  *sql.DB
)

func main() {
	age := 27
	rows, err := db.QueryContext(ctx, "SELECT name FROM users WHERE age=?", age)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()
	names := make([]string, 0)

	for rows.Next() {
		var name string
		if err := rows.Scan(&name); err != nil {
			// Check for a scan error.
			// Query rows will be closed with defer.
			log.Fatal(err)
		}
		names = append(names, name)
	}
	// If the database is being written to ensure to check for Close
	// errors that may be returned from the driver. The query may
	// encounter an auto-commit error and be forced to rollback changes.
	rerr := rows.Close()
	if rerr != nil {
		log.Fatal(err)
	}

	// Rows.Err will report the last error encountered by Rows.Scan.
	if err := rows.Err(); err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s are %d years old", strings.Join(names, ", "), age)
}

テストについて

オブジェクトのモックを作るときはgo-mockなどを利用するだろう。

sql.DBオブジェクトもmockを作ることができて、sql-mockというライブラリもある。

また、Dockerを使ってコードの中からSQLサーバを立ち上げたいときはtest-mysqldライブラリが使える。

コードの中からDockerを立ち上げるdockertestというライブラリもあるので、Dockerイメージで立ち上げるときはこちらを使う。

もっと深い話は@codehexさんや__timakin__さんの記事を読むと良い。

CircleCIについて

省略してしまったが、CircleCIの設定方法の基本は以下になる。

CircleCI上でMySQLなどのDBサーバを使う設定をしたいときは、以下のページを参考にconfig.ymlを書いていけば良い。

最後に

SpeakerDeckにアップしている資料は少し古いので直したいのだが、オリジナルデータのKeyNoteファイルが壊れてしまって開けなくなってしまった。 KeyNoteを閉じる→開くとファイルが壊れている、ということが度々あるのだが使い方が悪いのだろうか…

GoConで発表する(くらいのスキルを身につける)のは長年の夢だったので今回登壇できてとても嬉しい。 ただ、今回の内容はビギナー向けの発表だった。 初心者向けがよくないわけではないが、他の発表者のみなさんのような中級者・上級者向けの発表もできる、あるいは議論できるくらいのスキルを身につけていきたい。

Gopherくんかわいい。

参考

関連記事