.../articles/

Golang: xo + sqlx

Golangでデータベースを操作するためにxoとsqlxを併用する方法について。

Golangでデータベースを操作する場合はテーブルをStructに対応付けることが多いと思います。

しかしデータベースも必要に応じて構造を更新していくことになるため、コードをその時々の構造に追従するのは人の手で行うのは意外と面倒です(なによりミスも起きやすくなる)。

そこでデータベースに合わせてコードを生成することができる xo と標準ライブラリの database/sql の拡張と謳う sqlx を使うことでこのあたりの運用を簡単にしてみようと思います。


前提として以下の環境が構築済みとしています。

PostgreSQL

バージョンは9.6、以下のDDLで users テーブルを作成済み。

CREATE TABLE users (
    user_id bigserial PRIMARY KEY,
    email varchar(100) NOT NULL,
    created_at timestamp NOT NULL,
    updated_at timestamp NOT NULL
);

Golang

Golangのバージョンは1.12で xo がインストール済み。


xoについて

READMEに従って以下のコマンドを実行すると、 models 以下にファイルが出力されます。

# generate code for a postgres schema
$ xo pgsql://user:pass@host/dbname -o models

上述の users テーブルは models/user.xo.go として以下のように出力されます。

// Package models contains the types for schema 'public'.
package models

// Code generated by xo. DO NOT EDIT.

import (
   "errors"
   "time"
)

// User represents a row from 'public.users'.
type User struct {
   UserID    int64     `json:"user_id"`    // user_id
   Email     string    `json:"email"`      // email
   CreatedAt time.Time `json:"created_at"` // created_at
   UpdatedAt time.Time `json:"updated_at"` // updated_at

   // xo fields
   _exists, _deleted bool
}

// 以下略

データベースのマイグレーションと合わせて xo でモデル定義を更新することで、データベースとコードの構造の乖離を防ぐことができます。

sqlxについて

sqlx の使い方自体はREADMEなどを見てもらうとして、以下のページではStructのタグについての記述があります。

You can use the db struct tag to specify which column name maps to each struct field, or set a new default mapping with db.MapperFunc().

これについては必須というわけではないようですが、明示的にタグでカラムを指定するほうが望ましいでしょう。


xo + sqlx

xo で出力されるStructのタグは json のみなので、 sqlx に対応させるために db タグを追加してみます。

出力をカスタマイズするにはREADMEにあるように、テンプレートファイルを用意することになります。

もととなるテンプレートを templates にコピーしたら必要な箇所を編集し、それらのテンプレートを使用することができます。

# change to working project directory
$ cd $GOPATH/src/path/to/my/project

# create a template directory
$ mkdir -p templates

# copy xo templates for postgres
$ cp "$GOPATH/src/github.com/xo/xo/templates/*" templates/

# remove xo binary data
$ rm templates/*.go

今回はPostgreSQLの出力にタグを追加したいので postgres.type.go.tpl を編集します。

編集するのは10行目のタグを記述している箇所、ここに db:"{{ .Col.ColumnName }}" を追記します。

- 	{{ .Name }} {{ retype .Type }} `json:"{{ .Col.ColumnName }}"` // {{ .Col.ColumnName }}
+	{{ .Name }} {{ retype .Type }} `json:"{{ .Col.ColumnName }}" db:"{{ .Col.ColumnName }}"` // {{ .Col.ColumnName }}

オプションでテンプレートを指定することでカスタマイズしたモデル定義を出力できます。

$ xo pgsql://user:pass@localhost/dbname -o models --template-path templates/

これにより出力される user.xo.go は以下、タグに db が追加されるようになりました。

// Package models contains the types for schema 'public'.
package models

// Code generated by xo. DO NOT EDIT.

import (
	"errors"
	"time"
)

// User represents a row from 'public.users'.
type User struct {
	UserID    int64     `json:"user_id" db:"user_id"`       // user_id
	Email     string    `json:"email" db:"email"`           // email
	CreatedAt time.Time `json:"created_at" db:"created_at"` // created_at
	UpdatedAt time.Time `json:"updated_at" db:"updated_at"` // updated_at

	// xo fields
	_exists, _deleted bool
}

// 以下略

これで xo で出力したモデル定義を sqlx に合わせることができました。

次はマイグレーションと合わせた運用についてまとめてみようと思います。

.../articles/

Articles

記事

AWS AmplifyにmonorepoのNext.js(App Router)をデプロイする

AWS AmplifyにmonorepoのNext.js(App Router)をデプロイする

monorepo管理しているNext.jsをAmplifyにデプロイしようとした際にいくつか躓く内容があったのでまとめておきます。

リモートワーク・オンライン会議でも、スムーズに制作を進めるために大切なこと[資料編]

リモートワーク・オンライン会議でも、スムーズに制作を進めるために大切なこと[資料編]

コロナ禍の影響により、リモートワークの導入をおこなっている制作会社も多く、実際に弊社でも導入しています。

売れるECサイトデザインを作るために。参考にしたいおしゃれな事例の探し方。

売れるECサイトデザインを作るために。参考にしたいおしゃれな事例の探し方。

売れるECサイトのデザインは、「この形式」という決まりはありません。ECサイトで売り上げを上げるなら、しっかりとしたコンセプトと、コンセプトを決定するまでのリサーチが必要です。

制作会社の考える、業務効率化ツールのおすすめ。個人でも使いやすいサービスなど。

制作会社の考える、業務効率化ツールのおすすめ。個人でも使いやすいサービスなど。

新型コロナウイルス感染拡大の影響で、リモートワークが主流になり、弊社でも週のほとんどは各自宅で作業をしています。

Figmaでデザインのコミット履歴を残せるプラグイン【Thought Recorder】をリリースしました

Figmaでデザインのコミット履歴を残せるプラグイン【Thought Recorder】をリリースしました

Figmaを利用するWebデザイナーの助けになれると嬉しいです。使い方は本記事をご覧ください。

ECの構築方法、おすすめのECサービス。

ECの構築方法、おすすめのECサービス。

ファッションや家電、スーパーの買い物でさえもECサイトを利用することが当たり前になりました。加えて新型コロナウイルスの影響もあり、弊社にも「どんなプラットフォームを利用したら良いか」「どれくらいコストがかかるのか」などECに関するさまざまなご相談を頂きます。

FastAPIのスキーマクラスをOpenAPIから生成する方法

FastAPIのスキーマクラスをOpenAPIから生成する方法

PythonでAPIを構築する要件があり、フレームワークに比較的モダンなFastAPIを採用しました。FastAPIはバックエンドの開発を行えば自動でOepnApi定義を生成する機能が備わっていますが、今回はこれを使わず、事前に用意したOepnApi定義からFastAPIで利用するスキーマクラスを生成する方法を紹介します。

Laravel 日本一解りやすい全文検索のマイグレーション記載方法解説

Laravel 日本一解りやすい全文検索のマイグレーション記載方法解説

Laravel + MySQLで全文検索を実装する

とあるPythonのソースで sys.path.append としたく無かった話

とあるPythonのソースで sys.path.append としたく無かった話

とあるプロジェクトのとあるソースコードのレビューをしてた時、「ソースコードの参照がうまくいってなかったので修正しました」とレビュー依頼がきました。 ディレクトリ構造 ``` module L __init__.py L main.py L tests L __init__.py L test_main.py ``` ソースコード ``` python tests/test_main.py sys.path.append(os.path.abspath("..")) from main import fuga ``` 今まで案件でPythonに触れる機会も結構ありましたが、なんとなく使ってきた部分も多く、この書き方が良いのか悪いのか判別できなかったので、改めてPythonのモジュールのインポートに関して調べてみたのでブログにしました。普段PHPを書いている事が多くPythonに関して何も分からないので初心者向けの内容になっていると思います。

GiFT1号目新卒デザイナーの2021年振り返り

GiFT1号目新卒デザイナーの2021年振り返り

いつの間に、年末ですね。入社してもう、9ヶ月も立っていたようです。2021年の振り返りを記事にしました。

すべての記事

お問い合わせ