go buildとは?Go言語のビルドコマンドを初心者向けに徹底解説!

「go buildって何をするコマンド?」
「Goのプログラムをどうやって配布用にビルドするの?」
「クロスコンパイルで他のOSでも動くバイナリを作りたい」

Go言語でプログラムを書いたら、次は実行可能ファイルを作る必要がありますよね。その時に使うのがgo buildコマンドです。

このコマンドは、書いたGoのソースコードを、パソコンで直接実行できる形式(バイナリファイル)に変換してくれます。とてもシンプルで使いやすいツールなんです。

この記事では、go buildの基本から、実践的なオプション、クロスコンパイル、最適化まで、初心者の方でも分かるように丁寧に解説していきますね。

スポンサーリンク

go buildって何?基本を理解しよう

ビルドとは

まず、ビルド(build)という言葉について確認しておきましょう。

ビルドは、人間が読み書きできるソースコード(プログラムの文章)を、コンピューターが直接実行できる形式(機械語)に変換する作業のことです。

例えるなら:

  • ソースコード = 設計図や材料
  • ビルド = 組み立て作業
  • 実行可能ファイル = 完成品

Go言語で書いた.goファイルを、Windowsなら.exe、LinuxやMacならそのまま実行できるバイナリファイルに変換するのがビルドです。

go buildの役割

go buildは、Goの標準ツールの1つで、コンパイル(変換)とリンク(結合)を行ってくれます。

具体的には:

  1. .goファイルを読み込む
  2. 構文をチェックする
  3. 依存するパッケージも含めてコンパイルする
  4. 1つの実行可能ファイルにまとめる

これらが全部、go buildというコマンド1つで完了します。便利ですよね。

go runとの違い

Goにはgo runというコマンドもあります。違いを理解しておきましょう。

go run

go run main.go
  • その場でコンパイルして実行
  • 実行可能ファイルは作らない(一時的に作って削除)
  • 開発中のテストに便利

go build

go build main.go
  • 実行可能ファイルを作成
  • 何度でも実行できる
  • 他の人に配布できる

開発中はgo run、配布用はgo buildと使い分けるのが一般的です。

基本的な使い方

実際にgo buildを使ってみましょう。

最もシンプルな例

main.goというファイルを作ります:

package main

import "fmt"

func main() {
    fmt.Println("Hello, Go!")
}

ビルドします:

go build main.go

これで実行可能ファイルが作られます。

Windowsの場合:
main.exeが作られます。

LinuxやMacの場合:
mainが作られます。

実行してみましょう:

Windows:

.\main.exe

Linux/Mac:

./main

「Hello, Go!」と表示されれば成功です!

プロジェクト全体をビルド

プロジェクトのフォルダ内で、ファイル名を指定せずに実行すると、プロジェクト全体がビルドされます:

cd my-project
go build

この場合、フォルダ名と同じ名前の実行可能ファイルが作られます。

フォルダ構造:

my-project/
├── main.go
├── utils.go
└── config.go

実行:

go build

結果:
my-project(またはmy-project.exe)が作られます。

出力ファイル名を指定

-oオプションで、好きな名前を付けられます:

go build -o app main.go

これでapp(またはapp.exe)という名前のファイルが作られます。

実用例:

go build -o bin/myapp
go build -o dist/production-app.exe

便利なオプション一覧

go buildには様々なオプションがあります。よく使うものをご紹介しますね。

-o(出力ファイル名指定)

go build -o myapp main.go

カスタムの名前で保存できます。

-v(詳細表示)

go build -v

ビルド中のパッケージ名が表示されます。何が処理されているか分かるので、デバッグに便利です。

-a(全て再ビルド)

go build -a

キャッシュを使わず、全てのパッケージを再ビルドします。通常は不要ですが、クリーンなビルドが欲しい時に使います。

-race(競合検出)

go build -race

並行処理での競合状態(データの競合)を検出する機能を有効にします。マルチスレッドプログラムのデバッグに便利です。

-ldflags(リンカフラグ)

go build -ldflags="-s -w"

リンカー(プログラムを結合するツール)に指定を渡せます。

よく使うフラグ:

  • -s:シンボルテーブルを削除(デバッグ情報を除去)
  • -w:DWARF情報を削除(さらにデバッグ情報を除去)
  • これらでファイルサイズを削減できます

バージョン情報を埋め込む例:

go build -ldflags="-X main.version=1.0.0"

プログラム内の変数に値を設定できます。

-tags(ビルドタグ)

go build -tags=production

条件付きコンパイルができます。環境によってコードを切り替えたい時に便利です。

コード例:

//go:build production

package config

const Debug = false

-trimpath(パス情報削除)

go build -trimpath

ビルドしたマシンのパス情報をバイナリから削除します。セキュリティやプライバシーのために使います。

クロスコンパイルをマスターしよう

Goの最大の魅力の1つが、クロスコンパイルです。

クロスコンパイルとは

自分のパソコンで、別のOS・アーキテクチャ向けのバイナリを作ることです。

例えば:

  • Macで、Windows用のexeファイルを作る
  • Windowsで、Linux用のバイナリを作る
  • Intel CPUのマシンで、ARM用のバイナリを作る

通常、他の言語では難しい作業ですが、Goなら超簡単なんです。

環境変数の設定

クロスコンパイルは、GOOSGOARCHという環境変数で制御します。

GOOS:ターゲットのOS

  • windows
  • linux
  • darwin(macOS)
  • freebsd
  • など

GOARCH:ターゲットのCPUアーキテクチャ

  • amd64(64ビットIntel/AMD)
  • 386(32ビットIntel)
  • arm(ARM 32ビット)
  • arm64(ARM 64ビット)
  • など

実践例:様々なプラットフォーム向けビルド

Mac/Linuxから、Windows 64ビット向け:

GOOS=windows GOARCH=amd64 go build -o app.exe

Windowsから、Linux 64ビット向け:

set GOOS=linux
set GOARCH=amd64
go build -o app

PowerShellの場合:

$env:GOOS="linux"
$env:GOARCH="amd64"
go build -o app

Mac Intel向け:

GOOS=darwin GOARCH=amd64 go build -o app

Mac Apple Silicon(M1/M2)向け:

GOOS=darwin GOARCH=arm64 go build -o app

Raspberry Pi向け:

GOOS=linux GOARCH=arm GOARM=7 go build -o app

複数プラットフォーム向けに一括ビルド

シェルスクリプトで自動化できます:

build-all.sh

#!/bin/bash

APP_NAME="myapp"
VERSION="1.0.0"

# Windows 64bit
GOOS=windows GOARCH=amd64 go build -o dist/${APP_NAME}-${VERSION}-windows-amd64.exe

# Linux 64bit
GOOS=linux GOARCH=amd64 go build -o dist/${APP_NAME}-${VERSION}-linux-amd64

# macOS Intel
GOOS=darwin GOARCH=amd64 go build -o dist/${APP_NAME}-${VERSION}-darwin-amd64

# macOS Apple Silicon
GOOS=darwin GOARCH=arm64 go build -o dist/${APP_NAME}-${VERSION}-darwin-arm64

echo "Build complete!"

実行:

chmod +x build-all.sh
./build-all.sh

一気に4つのプラットフォーム向けバイナリが作られます。

ビルドの最適化テクニック

より小さく、速いバイナリを作るテクニックをご紹介します。

ファイルサイズの削減

基本的な最適化:

go build -ldflags="-s -w" -o app

-s-wでデバッグ情報を削除し、ファイルサイズを削減します。

さらに圧縮(UPX使用):

go build -ldflags="-s -w" -o app
upx --best --lzma app

UPX(Ultimate Packer for eXecutables)というツールで、さらに50〜70%ほど圧縮できます。

サイズ比較例:

  • 通常ビルド:10MB
  • -s -w付き:7MB
  • UPX圧縮後:3MB

ビルド時間の短縮

並列ビルドの最大化:

go build -p 8

-pオプションで並列実行数を指定できます。CPUコア数に合わせて調整しましょう。

キャッシュの活用:
Goは自動的にビルド結果をキャッシュしますが、意図的にクリアしたい場合:

go clean -cache

静的リンク

外部ライブラリへの依存を減らし、完全に自己完結したバイナリを作ります:

CGO_ENABLED=0 go build -a -installsuffix cgo

特にDockerコンテナで動かす時に便利です。

ビルド情報の埋め込み

バージョン、ビルド日時、Gitコミットハッシュなどを埋め込む方法:

main.go

package main

import "fmt"

var (
    version   = "dev"
    buildTime = "unknown"
    gitCommit = "unknown"
)

func main() {
    fmt.Printf("Version: %s\n", version)
    fmt.Printf("Built: %s\n", buildTime)
    fmt.Printf("Commit: %s\n", gitCommit)
}

ビルド:

go build -ldflags="-X main.version=1.0.0 -X main.buildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ) -X main.gitCommit=$(git rev-parse HEAD)"

実行すると、ビルド時の情報が表示されます。

実践的なビルドパターン

実際のプロジェクトで使える、実践的なパターンをご紹介します。

パターン1:開発用と本番用の切り替え

config.go

//go:build !production

package config

const (
    Debug      = true
    APIBaseURL = "http://localhost:8080"
)

config_prod.go

//go:build production

package config

const (
    Debug      = false
    APIBaseURL = "https://api.production.com"
)

開発用ビルド:

go build -o app-dev

本番用ビルド:

go build -tags=production -o app-prod

パターン2:Makefileで自動化

Makefile

APP_NAME=myapp
VERSION=1.0.0
BUILD_TIME=$(shell date -u +%Y-%m-%dT%H:%M:%SZ)
GIT_COMMIT=$(shell git rev-parse HEAD)

LDFLAGS=-ldflags "-s -w -X main.version=$(VERSION) -X main.buildTime=$(BUILD_TIME)"

.PHONY: build clean test

build:
    go build $(LDFLAGS) -o bin/$(APP_NAME)

build-all:
    GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o dist/$(APP_NAME)-windows.exe
    GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o dist/$(APP_NAME)-linux
    GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o dist/$(APP_NAME)-darwin

clean:
    rm -rf bin dist
    go clean

test:
    go test -v ./...

release: clean build-all
    cd dist && sha256sum * > checksums.txt

使い方:

make build          # 現在のOS用にビルド
make build-all      # 全プラットフォーム向けビルド
make test           # テスト実行
make release        # リリース用パッケージ作成

パターン3:Dockerでビルド

マルチステージビルドで、最小限のDockerイメージを作ります:

Dockerfile

# ビルドステージ
FROM golang:1.21-alpine AS builder

WORKDIR /app
COPY . .

RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags="-s -w" -o myapp

# 実行ステージ
FROM scratch

COPY --from=builder /app/myapp /myapp

ENTRYPOINT ["/myapp"]

ビルドと実行:

docker build -t myapp:latest .
docker run myapp:latest

scratchイメージを使うことで、5MB以下の超軽量イメージになります。

パターン4:CIでの自動ビルド

GitHub Actionsでの自動ビルド例:

.github/workflows/build.yml

name: Build

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Set up Go
      uses: actions/setup-go@v4
      with:
        go-version: '1.21'

    - name: Build
      run: |
        go build -v -ldflags="-s -w" -o myapp

    - name: Test
      run: go test -v ./...

    - name: Upload artifact
      uses: actions/upload-artifact@v3
      with:
        name: myapp
        path: myapp

よくある問題と解決法

go buildを使っていると遭遇する、典型的な問題と対処法です。

問題1:「package xxx is not in GOROOT」

エラー:

package github.com/user/repo is not in GOROOT

原因:
依存パッケージがダウンロードされていない。

解決法:

go mod download
go build

または、モジュールを初期化:

go mod init myapp
go mod tidy
go build

問題2:CGOが原因でクロスコンパイルできない

エラー:

cgo: C compiler "gcc" not found

原因:
CGO(C言語との連携)を使うパッケージがある場合、クロスコンパイルが複雑になります。

解決法:
CGOを無効化:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build

ただし、一部のパッケージ(データベースドライバなど)は動作しなくなる可能性があります。

問題3:ビルドサイズが大きすぎる

症状:
Hello Worldレベルのプログラムなのに、10MBを超える。

原因:
デバッグ情報が含まれている。

解決法:

go build -ldflags="-s -w" -o app

さらに:

go build -ldflags="-s -w" -trimpath -o app
upx --best app

問題4:「cannot execute binary file」

症状:
LinuxでビルドしたファイルをWindowsで実行しようとしてエラー。

原因:
OSが違うバイナリを実行しようとしている。

解決法:
正しいOS向けにビルドし直す:

GOOS=windows GOARCH=amd64 go build -o app.exe

問題5:ビルドが遅い

原因:

  • 大量の依存パッケージ
  • キャッシュが無効化されている
  • 並列実行数が少ない

解決法:

並列ビルドを増やす:

go build -p 8

不要なリビルドを避ける:

# -aオプションを外す
go build

モジュールキャッシュを確認:

go env GOMODCACHE

ビルドタグの活用

条件付きコンパイルで、環境に応じたビルドができます。

基本的な使い方

logger_dev.go

//go:build dev

package main

import "log"

func setupLogger() {
    log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
    log.Println("Development logger initialized")
}

logger_prod.go

//go:build prod

package main

import "log"

func setupLogger() {
    log.SetFlags(0)
}

main.go

package main

func main() {
    setupLogger()
    // アプリケーションのコード
}

ビルド:

# 開発版
go build -tags=dev -o app-dev

# 本番版
go build -tags=prod -o app-prod

OS別のコード

file_unix.go

//go:build linux || darwin

package main

import "syscall"

func getSystemInfo() string {
    return "UNIX system"
}

file_windows.go

//go:build windows

package main

func getSystemInfo() string {
    return "Windows system"
}

ビルドすると、自動的に適切なファイルが選ばれます。

まとめ:go buildを使いこなそう

go buildは、シンプルながら強力なビルドツールです。

この記事のポイントをおさらい:

  • go buildはソースコードを実行可能ファイルに変換するコマンド
  • -oオプションで出力ファイル名を指定できる
  • クロスコンパイルが超簡単(GOOSとGOARCHを指定するだけ)
  • -ldflags="-s -w"でファイルサイズを削減
  • ビルドタグで条件付きコンパイルが可能
  • Makefileやスクリプトで自動化できる
  • Docker、CI/CDとの連携も簡単
  • 静的リンクで依存関係のないバイナリを作成
  • バージョン情報などをビルド時に埋め込める

Goの魅力の1つは、クロスコンパイルの簡単さです。1つのマシンで、Windows、Linux、Mac、さらにはRaspberry Pi向けのバイナリまで作れるのは本当に便利ですよね。

最初はgo buildだけで十分ですが、慣れてきたら様々なオプションを試して、最適なビルド方法を見つけてください。この記事が、あなたのGo開発の助けになれば嬉しいです!

コメント

タイトルとURLをコピーしました