競プロの Go から Web の Go へ
読了目安 約3分
提出して終わりの競プロと、複数ファイルで長く育てる Web 開発とで、Go の書き方の前提がどう変わるかを整理します。
この章の目次
競プロで身につけた Go の文法は、Web 開発でもそのまま使えます。 変わるのは文法ではなく、コードが置かれる状況のほうです。
ブラウザで動かす Hello World
package main
import "fmt"
func main() {
fmt.Println("Hello, ねじき教室!")
}この Part のコード例の多くは、「▶ エディタで実行」で右のエディタに読み込み、書き換えながら動かせます。
提出して終わりか、動かし続けるか
競プロのプログラムは 1 ファイルで完結し、AC が出た瞬間に役目を終えます。
読むのは書いた本人だけなので、変数名が a でも困りません。
本番の Web サービスのコードは、正反対の条件に置かれます。
- サービスが続くかぎり動き続け、機能追加や不具合修正のたびに読み直される
- 読むのは、事情を知らないチームメイトや、細部を忘れた半年後の自分
- 規模は 1 ファイルに収まらず、数十から数百のファイルに分かれて育つ
この Part で学ぶ「パッケージ」「エラー処理」「テスト」は、どれもこの条件で長く動かして何度も読むための道具です。
プロジェクトは go mod init から始まる
モジュールは、ひとまとまりの Go プロジェクトを指す単位で、go mod init で作ります。
mkdir hello-web
cd hello-web
go mod init example.com/hello-web実行すると go.mod というファイルができ、モジュール名と Go のバージョン、使う外部パッケージとそのバージョンが記録されます。
だから、チームで同じリポジトリを共有すれば、同じビルド結果になります。
プロジェクトが育つと、ディレクトリはたとえばこうなります。
hello-web/
├── go.mod
├── main.go
└── user/
└── user.goディレクトリが、コードを分ける単位(パッケージ)になります。 その分け方は次章で扱います。
go run と go build と go fmt
- go run:ソースコードをその場でコンパイルして実行します。競プロ環境の「実行」ボタンに相当し、開発中の動作確認に使います。
- go build:実行ファイルを作ります。本番のサーバーには、ソースコードではなくこの実行ファイルを置いて動かします。
- go fmt:インデントや空白の入れ方を、Go 公式のルールに揃えます。
go run . # 開発中の実行
go build . # 実行ファイルを作る
go fmt ./... # プロジェクト全体を整形するgo fmt の整形ルールは、言語側で 1 つに決まっています。
誰が書いたコードも同じ見た目になり、読む速度が上がります。
エディタに保存時の自動実行を設定するのが普通です。
./...は「このディレクトリ以下のすべてのパッケージ」を意味する、Go のコマンドに共通の記法です。
読まれる回数のほうが書く回数より多い
競プロのコードは 1 回書いて 1 回提出しますが、本番のコードは修正やレビューや調査のために何十回も読まれます。 だから、書く速さより読みやすさに投資するほうが、合計の時間は短くなります。 この後の章で扱う判断は、ほとんどがこの価値観に立ちます。
試してみよう
次のプログラムは動きますが、何を計算しているのか名前から読み取れません。
package main
import "fmt"
func main() {
a := 3
b := 120
c := 500
d := b*a + c
fmt.Println(d)
}これは「単価 120 円の商品を 3 個買い、送料 500 円を足した合計金額」の計算です。
変数名を quantity、unitPrice、shippingFee、total のような説明的な名前に書き換えて、出力が 860 のまま変わらないことを確かめてください。