🔩 ねじき教室 Go と Web の教室

競プロの Go から Web の Go へ

読了目安 約3分

提出して終わりの競プロと、複数ファイルで長く育てる Web 開発とで、Go の書き方の前提がどう変わるかを整理します。

この章の目次

競プロで身につけた Go の文法は、Web 開発でもそのまま使えます。 変わるのは文法ではなく、コードが置かれる状況のほうです。

ブラウザで動かす Hello World

Go
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 回提出しますが、本番のコードは修正やレビューや調査のために何十回も読まれます。 だから、書く速さより読みやすさに投資するほうが、合計の時間は短くなります。 この後の章で扱う判断は、ほとんどがこの価値観に立ちます。

試してみよう

次のプログラムは動きますが、何を計算しているのか名前から読み取れません。

Go
package main

import "fmt"

func main() {
	a := 3
	b := 120
	c := 500
	d := b*a + c
	fmt.Println(d)
}

これは「単価 120 円の商品を 3 個買い、送料 500 円を足した合計金額」の計算です。 変数名を quantityunitPriceshippingFeetotal のような説明的な名前に書き換えて、出力が 860 のまま変わらないことを確かめてください。