Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?

posted at

updated at

Go (Golang) コマンドラインツールの作り方

Golang バージョン 1.16 以上をを想定しています
環境の構築方法については次の記事を参照してください:
Docker とVisual Studio Code を使った Go (Golang) 開発環境構築 - Qiita

基本

まずは Golang プロジェクトを初期化します

プロジェクト用フォルダーを作成し、そのフォルダーの直下で次のコマンドを実行します:

go mod init <リポジトリーのパス>

例:

go mod init github.com/yukihiko-shinoda/go-commandline-tool

※ リポジトリーのパスは後から変えることもできます

すると、ファイル: go.mod が作成されます

project/
+---go.mod

次に .go ファイルを作成します
例:

project/
+---commandline_tool.go
+---go.mod
commandline_tool.go
package main

func main() {
    println("Hello world!")
}

このとき、次のことに気をつけます:

  • packagemain とします
  • コマンドラインツールを実行したときの処理を main() に定義します

このコードをコマンドラインツールとしてインストールします
インストールには 2 通りの方法があります

go install

go install とだけ実行すると、
最初に実行した go mod init <リポジトリーのパス> のリポジトリー名の部分が
コマンド名になります:

$ go install
$ go-commandline-tool
Hello world!

go install <.go ファイル名>

go install に続けて .go ファイル名を入力すると、
.go ファイル名の拡張子を除いた部分の文字列がコマンド名になります:

$ go install commandline_tool.go
$ commandline_tool
Hello world!

複数のコマンドラインツールを作成する場合

1 つのパッケージ内に main() を複数定義することはできないので、
リポジトリーを分けるか、サブフォルダーを作成します

サブフォルダーを作成する場合は、cmd フォルダーを作成し、
さらにコマンドごとにサブフォルダーを作成するのが一般的であるようです:

project/
+----cmd/
    +----command1/
    |    +----command1.go
    +----command2/
         +----command2.go

ちなみに、Golang 公式のフォルダー構成の推奨は特になく、
cmd フォルダーについても公式の言及はありませんが、
多くの Golang プロジェクトが
次の非公式ベストプラクティスに倣って cmd フォルダーを作成しているようです:

参考: golang-standards/project-layout: Standard Go Project Layout

.go ファイルの package は main にし、
それぞれにコマンド実行時の処理を main() として定義します
次のコマンドで go ファイル名のコマンドが実行できるようになります:

$ go install cmd/command1/command1.go
$ go install cmd/command2/command2.go
$ command1
Hello world 1!
$ command2
Hello world 2!

リポジトリーからコマンドラインツールをインストール

以下の説明は Git などバージョン管理システムの知識を前提としています
バージョン管理システムの基礎については次の記事を参照してください:
Linux 知識の要らない Git 講座 目次 | ultra code

作成したコマンドラインツールを Git などのリポジトリーに push して、
バージョンを示すタグを付けておくことで、
Golang のインストールされている環境にいつでもコマンドラインツールをインストールできます:

go install <リポジトリーの main パッケージのフォルダーまでのパス>@<バージョンを示すタグ>

例 1:
ルートパッケージがコマンドラインツールの、タグ: v1.0.0 が示すバージョンをインストールする場合:

go install github.com/yukihiko-shinoda/go-commandline-tool@v1.0.0

例 2:
cmd/command1/command1.go にコマンドラインツールを実装しており、
タグ: v1.0.0 が示すバージョンをインストールする場合:

go install github.com/yukihiko-shinoda/go-commandline-tool/cmd/command1@v1.0.0

この場合、コマンド名は main() が定義されている .go ファイル名……ではなく、
その .go ファイルの親フォルダー名になります

インストール方法ごとのコマンド名まとめ

今まで見てきたように、インストール方法によってコマンド名が変わってしまいます
まとめると、次のようになります:

インストール方法 コマンド名
ローカルの go.mod を含むフォルダーで go install 最初に実行した go mod init <リポジトリーのパス> のリポジトリー名の部分
go install <.go ファイル名> .go ファイル名の拡張子を除いた部分の文字列
リポジトリーからコマンドラインツールをインストール リポジトリーの main パッケージのフォルダー名

開発時とリリース時でコマンド名が変わらないようにする方法

次のようにすると、開発時とリリース時でコマンド名が変わらないようにできます

プロジェクト直下にコマンドラインツールを作成するとき

開発時にテストのためコマンドラインツールをインストールするときは、
ファイル名を指定せずに go install するようにします

サブフォルダーを用意してコマンドラインツールを作成するとき

フォルダー名と main() を定義する .go ファイル名を同じ名前で作成するようにします

例:

project/
+----cmd/
    +----command1/
    |    +----command1.go
    +----command2/
         +----command2.go
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?