株式会社エスロジカル
株式会社エスロジカル
SSL証明書(DV、OV、EV)、セキュリティ、Web開発、Linux開発、Go言語

HOME > 技術ドキュメント > Go CLI ツール開発入門

Go CLI ツール開発入門


Go 言語はシングルバイナリにコンパイルできるため、依存関係のない配布しやすい CLI ツールの開発に適しています。 本記事では標準ライブラリの flag パッケージを使ったオプション解析から、サブコマンド・ファイル操作・ 外部 API 呼び出しまで、CLI ツール開発に必要な基礎を解説します。
Go のインストールは Go 言語 開発環境構築 を参照してください。


package main

import (
    "flag"
    "fmt"
)

func main() {
    name := flag.String("name", "World", "greeting target")
    count := flag.Int("n", 1, "repeat count")
    verbose := flag.Bool("v", false, "verbose output")

    flag.Parse()

    if *verbose {
        fmt.Printf("name=%s, count=%d\n", *name, *count)
    }
    for i := 0; i < *count; i++ {
        fmt.Printf("Hello, %s!\n", *name)
    }
}
go run main.go -name Go -n 3 -v
# name=Go, count=3
# Hello, Go!
# Hello, Go!
# Hello, Go!

flag.Parse()
args := flag.Args() // フラグ以外の引数を取得
if len(args) == 0 {
    fmt.Fprintln(os.Stderr, "usage: mytool [options] <file>")
    os.Exit(1)
}
fmt.Println("file:", args[0])

git commitdocker run のようなサブコマンドは flag.NewFlagSet で実装します。

package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {
    if len(os.Args) < 2 {
        fmt.Fprintln(os.Stderr, "usage: mytool <command> [options]")
        fmt.Fprintln(os.Stderr, "  add    add a record")
        fmt.Fprintln(os.Stderr, "  list   list records")
        os.Exit(1)
    }

    switch os.Args[1] {
    case "add":
        addCmd := flag.NewFlagSet("add", flag.ExitOnError)
        name := addCmd.String("name", "", "record name")
        addCmd.Parse(os.Args[2:])
        fmt.Printf("adding: %s\n", *name)

    case "list":
        listCmd := flag.NewFlagSet("list", flag.ExitOnError)
        all := listCmd.Bool("all", false, "show all")
        listCmd.Parse(os.Args[2:])
        fmt.Printf("listing (all=%v)\n", *all)

    default:
        fmt.Fprintf(os.Stderr, "unknown command: %s\n", os.Args[1])
        os.Exit(1)
    }
}

import (
    "bufio"
    "fmt"
    "os"
)

// 標準入力を1行ずつ読み取る
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
    line := scanner.Text()
    fmt.Println(line) // 標準出力
}

// エラーは必ず os.Stderr に出力する
fmt.Fprintln(os.Stderr, "error: something went wrong")
os.Exit(1)

os.Exit の注意点:os.Exit() を呼ぶと defer が実行されません。 リソースのクリーンアップが必要な場合は main 関数を run() 関数に分離し、 run() の戻り値で os.Exit を呼ぶパターンが推奨されます。


import (
    "bufio"
    "fmt"
    "os"
)

// ファイルを読み取る
f, err := os.Open("input.txt")
if err != nil {
    fmt.Fprintln(os.Stderr, "error:", err)
    os.Exit(1)
}
defer f.Close()

scanner := bufio.NewScanner(f)
for scanner.Scan() {
    fmt.Println(scanner.Text())
}

// ファイルに書き込む
out, err := os.Create("output.txt")
if err != nil {
    fmt.Fprintln(os.Stderr, "error:", err)
    os.Exit(1)
}
defer out.Close()

fmt.Fprintln(out, "written by Go")

import (
    "encoding/json"
    "fmt"
    "net/http"
    "os"
)

type Response struct {
    Status string `json:"status"`
    Data   string `json:"data"`
}

func fetchAPI(url string) (*Response, error) {
    resp, err := http.Get(url)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf("status: %d", resp.StatusCode)
    }

    var result Response
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return nil, err
    }
    return &result, nil
}

Go の net/http はデフォルトで TLS 証明書を検証します。接続先サーバーに有効な SSL証明書が必要です。


# 現在の環境向けにビルド
go build -o mytool .

# Linux (amd64) 向けビルド(他の OS から)
GOOS=linux GOARCH=amd64 go build -o mytool-linux .

# Windows 向けビルド
GOOS=windows GOARCH=amd64 go build -o mytool.exe .

# $GOPATH/bin にインストール(PATH が通っていれば mytool で呼べる)
go install .

# バイナリサイズを削減(デバッグ情報削除)
go build -ldflags="-s -w" -o mytool .

// calc_test.go
package main

import "testing"

func add(a, b int) int { return a + b }

func TestAdd(t *testing.T) {
    cases := []struct{ a, b, want int }{
        {1, 2, 3},
        {0, 0, 0},
        {-1, 1, 0},
    }
    for _, c := range cases {
        if got := add(c.a, c.b); got != c.want {
            t.Errorf("add(%d,%d) = %d, want %d", c.a, c.b, got, c.want)
        }
    }
}
go test ./...
go test -v ./...
go test -cover ./...

Go 言語 開発環境構築(Ubuntu 24.04 LTS) — インストール・go mod・クロスコンパイル
Go 言語 Web アプリ入門 — net/http サーバー、JSON REST API


Go の net/http はデフォルトで TLS 証明書を検証します。 自己署名証明書が設定されたサーバーには接続エラーになるため、 本番の API サーバーには公的 CA から発行された有効な SSL証明書が必要です。
エスロジカルではデジサート・サイバートラストの正規取扱代理店として、 2009年から16年以上、RapidSSL 3,960円/1年(税込)〜でSSL証明書を販売しています。審査サポート・インストール代行も対応しています。

SSL証明書の購入はこちら / SSL証明書とは? / インストール代行サービス


← 技術ドキュメント一覧へ戻る