Golangのコマンドラインプログラムを使用して

5639 ワード

総覧
Go言語はワクワクする新しい言語で、良い理由で広く歓迎されています.このチュートリアルでは、Goを使用してコマンドラインプログラムを作成する方法について説明します.このサンプル・プログラムはmulti-gitと呼ばれ、複数のリポジトリでgitコマンドを同時に実行できます.
クイックスタート
GoはC言語とUnixの最初のハッカーがGoogleで作成したC言語に似たオープンソース言語で、C++への嫌悪によって引き起こされた.Goの設計に表示され、継承、テンプレート、例外を回避するなど、いくつかの非常に一般的な選択が行われています.Goは簡単で、信頼性が高く、効率的です.最もユニークな機能は、いわゆるgoroutineとチャネルによって同時プログラミングを明示的にサポートすることです.
サンプルプログラムのプロファイリングを開始する前に、公式ガイドに従ってGo開発の準備をしてください.
Multi-Gitプログラム
Multi-gitプログラムは簡単だが役に立つGoプログラムである.チームのコードライブラリが複数のgitリポジトリに分散している場合は、通常、複数のリポジトリで変更を実行する必要があります.gitには複数のリポジトリの概念がないため、これは問題です.すべては単一のリポジトリをめぐっています.
ブランチを使用すると、これは特に面倒になります.使用する機能が3つのリポジトリに関連している場合は、各リポジトリに機能ブランチを作成し、チェックアウト、引き出し、プッシュ、マージを同時に行うことを覚えておく必要があります.これは些細なことではない.Multigitはリポジトリのセットを管理し、リポジトリ全体を一度に操作できます.現在のバージョンのmulti-gitでは、ブランチを個別に作成する必要がありますが、後でこの機能を追加する可能性があります.
Multi-gitの実装方法を探ることで、Goでコマンドラインプログラムを作成する方法について多くの知識を学ぶことができます.
包装と輸入
Goプログラムはパッケージ形式で編成されている.Multi-gitプログラムにはmainという名前が含まれている.goのファイル.ファイルの上部に、パッケージ名「main」を指定し、インポートリストを指定します.インポートはmulti-gitが使用する他のパッケージです.
package main



import (

    "flag"

    "fmt"

    "log"

    "os"

    "strings"

    "os/exec"

)

例えば、fmtパケットは、Cのprintfおよびscanfに類似したフォーマットI/Oに使用される.Goは、go getコマンドによって様々なソースからパッケージをインストールすることをサポートします.パッケージをインストールすると、最終的に$GOPATH環境変数の下のネーミングスペースに配置されます.git、subversion、mercurial、bazaarなどいくつかの一般的なバージョン制御フォーマットを使用して、GitHub、Bitbucket、Googleコード、Launchpad、IBM DevOpsサービスなどのさまざまなソースからパッケージをインストールできます.
コマンドラインパラメータ
コマンドラインパラメータは、プログラムに入力を提供する最も一般的な形式の1つです.これらは使いやすく、1行でプログラムを実行および構成し、さまざまな言語の強力な解析サポートを提供します.Goはこれをコマンドライン「フラグ」と呼び、コマンドラインパラメータ(またはフラグ)を指定および解析するためのフラグパッケージを有する.
通常、プログラムの開始時にコマンドラインパラメータを解析し、multi-gitはこの規則に従います.エントリポイントはmain()関数です.最初の2行には、コマンドとignoreErrorsという2つのタグが定義されています.各フラグには、名前、データ型、デフォルト値、ヘルプ文字列があります.flag.Parse()は、解析をプログラムに渡す実際のコマンドラインを呼び出し、定義されたフラグを入力する.
func main() {

    command := flag.String("command", "", "The git command")

    ignoreErrors := flag.Bool(

        "ignore-errors",

        false,

        "Keep running after error if true")

    flag.Parse()

定義されていないパラメータには、flag.Args()関数を使用してアクセスすることもできます.したがって、フラグは予め定義されたパラメータを表し、「args」は未処理のパラメータである.未処理のパラメータは0から始まるインデックスです.
かんきょうへんすう
プログラム構成のもう一つの一般的な形式は環境変数です.環境変数を使用すると、同じ環境で同じプログラムが複数回実行され、すべての実行で同じ環境変数が使用される場合があります.
Multigitは、「MG_ROOT」と「MG_REPOS」の2つの環境変数を使用します.Multigitは、共通の親ディレクトリを持つgitリポジトリのセットを管理することを目的としています.それは「MG_ROOT」です.リポジトリ名は、「MG_REPOS」でカンマ区切り文字列として指定されます.環境変数の値を読み込むには、os.Getenv()関数を使用します.
// Get managed repos from environment variables

    root := os.Getenv("MG_ROOT")

    if root[len(root) - 1] != '/' {

        root += "/"

    }



    repo_names := strings.Split(os.Getenv("MG_REPOS"), ",")

リポジトリ・リストの検証
ルートディレクトリとすべてのリポジトリの名前が見つかり、multi-gitは各リポジトリがrootの下にあることを検証し、gitリポジトリであることを確認しました.各リポジトリディレクトリで検索するようにチェックします.gitサブディレクトリは同じように簡単です.
まず、「repos」という文字列配列を定義します.その後、すべての買い戻し名を反復し、ルートディレクトリと買い戻し名を直列に接続してリポジトリパスを構築します.もし正しいなら.gitサブディレクトリの[os.Stat()]()呼び出しに失敗し、エラーが記録され、終了します.そうでない場合、リポジトリパスはrepos配列に追加されます.
var repos []string

    // Verify all repos exist and are actually git repos (have .git sub-dir)

    for _, r := range repo_names {

        path := root + r

        _, err := os.Stat(path + "/.git")

        if err != nil {

            log.Fatal(err)

        }

        repos = append(repos, path)

    }

Goには独自のエラー処理ツールがあり、関数は通常、戻り値とエラーオブジェクトを同時に返します.os.Stat()が2つの値を返す方法を確認します.この場合、""プレースホルダは、エラーのみに関心を持っているため、実際の結果を保存します.Goは非常に厳格で、命名変数を使用する必要があります.値を使用しない場合は「」に割り当てる必要があります.コンパイルエラーを回避します.
Shellコマンドの実行
これでgitコマンドを実行するリポジトリパスのリストが作成されました.gitコマンドラインを単一のコマンドラインパラメータ(フラグ)「command」と呼ばれる)として受信したことを覚えています.コンポーネント配列(gitコマンド、サブコマンド、オプション)に分割する必要があります.コマンド全体も文字列形式で保存され、表示に使用されます.
// Break the git command into components (needed to execute)

    var git_components []string

    for _, component := range strings.Split(*command, " ") {

        git_components = append(git_components, component)

    }

    command_string := "git " + *command

これで、各リポジトリを巡回し、各リポジトリでgitコマンドを実行する準備ができました.「for...range」ループ構造を再使用します.まずmulti-gitは、その作業ディレクトリを現在のターゲットリポジトリ「r」に変更し、gitコマンドを出力する.その後、exec.Command()関数を使用してコマンドを実行し、組み合わせられた出力(標準出力および標準エラー)を印刷します.
最後に、実行中にエラーがないかどうかを確認します.エラーが発生し、ignoreErrorsがfalseとしてマークされている場合、multi-gitは終了します.エラーを無視できるのは、コマンドが一部のリポジトリで失敗した場合に可能であるためです.たとえば、ブランチがあるすべてのリポジトリに「cool feature」というブランチをチェックアウトする場合は、ブランチがないリポジトリに失敗する必要はありません.
for _, r := range repos {

        // Go to the repo's directory

        os.Chdir(r);



        // Print the command

        fmt.Printf("[%s] %s
", r, command_string) // Execute the command out, err := exec.Command("git", git_components...).CombinedOutput() // Print the result fmt.Println(string(out)) // Bail out if there was an error and NOT ignoring errors if err != nil && !*ignoreErrors { os.Exit(1) } } fmt.Println("Done.")

結論
Goはシンプルで強力な言語です.大規模なシステムプログラミングのために設計されていますが、小型コマンドラインプログラムにも適用されます.Goの最小化設計は他の現代言語(例えばScaleとRust)と鮮明に対比され,ScaleとRustも非常に強く設計が合理的であるが,学習曲線は非常に急峻である.試してみることをお勧めします.その楽しさは尽きない.
翻訳:https://code.tutsplus.com/tutorials/lets-go-command-line-programs-with-golang--cms-26341