久しぶりにGoでAPIサーバーを書いてみる


概要

  • Go1.11からの新しい依存解決システムvgoはよい
  • 昔はGoでMongoDBを使うときはmgoを使っていたが、Go1.10+ならMongoDBの提供するmongo-go-driverが使える
  • freshを使えばGo製サーバーもライブリローディングしながら開発できる
  • 自分と同じようにGoを敬遠していた人もそろそろ始めどきかも

はじめに

久しぶりにGoを使ってJSON APIサーバーを書く機会がありました。

Goは1.6とかの時代にちょっと触っていたのですが1、Python, Ruby, Nodeといったスクリプト系言語を主な使用言語としている自分にはだるいな…と思うことが多々ありましたし、ディレクトリの場所が規定されてしまうというのも嫌だなぁと感じていました。
というわけでしばらくGoとはサヨウナラをしていました。

しかし最近バックエンドでGoを本格利用している会社の方が、最近Goもいろいろ変わっていてそろそろ再チャレンジするにはいい機会ですよ!と教えてもらいました。
特にGo1.11ではvgoという新しいバージョン管理システムが試験的に導入されており、これを使えばGOPATHはもういらないとのこと。

スキルセットとして低レイヤーなことができてWASM時代にも備えられる言語に触れておきたい、でも言語仕様が難しいやつはちょっと…という自分にとってGoはまさしく求めているものだという自覚はありました。
ちょうどプロトタイプを一個作ってみるといった案件があったため、これは何かの機会だと思い再びGoにチャレンジしてみました。

Docker

Goのバージョンを持っているPC全部でそろえるのは面倒なのでDockerを使うことに。
これだと別にvgo関係なくGOPATHどうこう気にする必要はなかったですね、、。

Dockerfile

FROM golang:1.11
WORKDIR /go/src/app

RUN go get github.com/pilu/fresh
ENV GO111MODULE=on
CMD ["fresh"]

ENV GO111MODULE=onによってvgoが使えるようになりますが、その後 go get がうまく動かなくなるので先に go get しています。
vgoが有効だと、相対パス記法でのインポートなど古い仕様を切り捨てるようになっているようでその影響かなぁと。

docker-compose.yaml

version: '3'
services:
  app:
    build:
      context: ./app/docker
    ports:
      - 8081:8081
    volumes:
      - ./app/src:/go/src/app
    command: fresh

開発ディレクトリ(./app/src)をDockerfileで指定した作業ディレクトリにマウントします。これでfreshを実行すると、自動的にmain.goが立ち上がるようです。freshについては後述。

まだビルドしてバイナリを出力するところまでは必要としていないので、まだその対応はしていません。

vgo

新しい依存管理システムです。importを書いておけば明示的にinstallとかしなくても必要があれば勝手にダウンロードしてくれる、Rubyのbundlerやnodeのnpmのようにバージョンロックできるというのが特徴です。

これを有効にすると相対パスを使ったインポートが使えなくなります。

main.go
import (
    "./lib",
)
...

main.goと同じディレクトリにgo.modを作成し、そこでプロジェクト名を定義し、<プロジェクト名>/<パス>というようにインポートします。

go.mod
module app
main.go
import (
    "app/lib"
)
...

参考
go 1.11のmodules(vgo)が有効な環境で相対importが cannot find module for path でエラーになった話。

mongo-go-driver

GoでMongoDBを使う際は、mgoというライブラリを使うのが定番だったようです。しかしこれはメンテナンス停止が宣言されており、フォークされたものを使っているケースが多いみたいですね。

しかし、MongoDBからmongo-go-driverというのがリリースされています。昨年12月にようやくアルファからベータになったばかりです。
Go1.10以上ということなので、これからGo+MongoDBという構成を導入するプロジェクトはこれを使ってみてもよさそうです。

fresh

freshというツールを使えば、Railsで開発しているのと同じようにライブリローディングが使えます。同じようなことを実現するツールにはginというものもあります。(Webフレームワークのginとは別物)

どちらもあまり更新されていないようです…。が、あるのとないのとだと開発中の気持ちよさが全然違います。
Goをだるいと感じていた最大の原因がコードを変えたらプロセスを立ち上げ直す必要がある、だったのでそれがなくなると気分的にはRailsで開発しているのとそう変わりません。

ちなみに、freshを使った環境構築はこちらを参考にしました。
Go v1.11 + Docker + fresh でホットリロード開発環境を作って愉快なGo言語生活

私はginではなく昔触ったことのあるechoを使っていますが、全く同じ方法でOKです。


GOPATH云々はDockerを使えばもともと気にする必要がなかったわけですが
vgoはGoの依存解決の決定版になるのでしょうか。まだ軽く触っている段階ですが、だいぶ体験としてはよいですね。bundle installとかnpm installとか、よくよく考えたら明示的に呼び出す必然性ってないですね。
(昔depというのがあったように思うのですが、同じようにまた新しいのが出てきたりしないでほしいなー…と思います。)

自分と同じように、昔触ったことがあるけどちょっとめんどくさくなって…という方は、そろそろ再チャレンジしてみてもよいかもしれません。


  1. そのころGoで「世界で闘うプログラミング力を鍛える150問」を解いていたときの残骸です。https://github.com/k5trismegistus/cracking-the-coding-interview-150