自動的にクロスコンパイル&あなたのGOアプリをリリース


前の記事では、A、A、A、Aを作成しました.とも.
我々はすでに見ているように、ゴランは、アプリケーションの種類のいくつかのために使用することができますが、知っている、私はCLIのアプリ&ツールを作成する愛、私は悪魔の哲学を愛し、私はGophersが大好きです.したがって、この記事では、ほとんどのツールを作成し、いくつかの試みベストプラクティスで、自動的にクロスプラットフォーム実行可能なバイナリを生成し、Githubアクションを介してGithubリリースを作成します.
レディ?

初期設定
まず、Githubの新しいリポジトリを作成します.
そのためにログインしましたGitHub website , 「リポジトリ」リンクをクリックして「新しい」グリーンボタンをクリックし、新しいリポジトリを作成しましたgophersay .
さて、ローカルコンピューターでは、Gitはこの新しいリポジトリをクローンします.
$ git clone https://github.com/scraly/gophersay.git
$ cd gophersay
ここでgoモジュール(依存関係管理)を初期化しなければなりません:
$ go mod init github.com/scraly/gophersay
go: creating new go.mod: module github.com/scraly/gophersay
これはgo.mod ファイル:
module github.com/scraly/gophersay

go 1.16
良いプラクティスとして、我々のデスクトップアプリケーションをコードを開始する前に、我々は簡単なコード組織を作成します.
次のフォルダを作成します
.
├── bin
├── README.md
└── go.mod
それですね.そうです、残りのコード組織はすぐに作成されます--)

アプリを作成しましょう

何が欲しいですか.
ご存知ですかcowsay それは牛によって言われたテキストを表示する単純なアプリです.

私は牛が好きです、しかし、私はより多くのGophersが好きです、それで、我々は牛の代わりにGopherで「カウエ」バージョンを作成したいです.
プログラムは、テキストと言うASCIIのユーザーとGopherによって書かれたテキストが表示されます.
このアプリは役に立たないかもしれませんが、いくつかの良いプラクティスを見ることができます.
最初にすべきことはGophers in ASCII format 私は、彼らを新しく作りましたgophers フォルダ.次のようなフォルダが必要です.
├── gophers
│   ├── gopher0.txt
│   ├── gopher1.txt
│   ├── gopher2.txt
│   └── gopher3.txt
クリエイトアmain.go ファイル.
まず、パッケージを初期化します.main , そして、すべての依存関係/librairiesはインポートする必要があります.
package main

import (
    "fmt"
    "log"
    "math/rand"
    "os"
    "strconv"
    "strings"
    "time"

    "embed"
)
次に、変数を初期化します.
// Hey, I want to embed "gophers" folder in the executable binary
// Use embed go 1.16 new feature (for embed gophers static files)
//go:embed gophers
var embedGopherFiles embed.FS
おかげで素晴らしいembed機能のおかげで含まれてGo 1.16 バージョンは、我々はgophers/ 変数のフォルダembedGopherFiles .
を作成しましょうmain() 機能
func main() {

    // Display usage/help message
    if len(os.Args) == 1 || (len(os.Args) == 2 && os.Args[1] == "-h") || (len(os.Args) == 2 && os.Args[1] == "--help") {
        usage := "GopherSay is inspired by Cowsay program.\nGopherSay allow you to display a message said by a cute random Gopher.\n\nUsage:\n   gophersay MESSAGE\n\nExample:\n   gophersay hello Gopher lovers"

        fmt.Println(usage)
        return
    } else if len(os.Args) > 1 {

        message := strings.Join(os.Args[1:], " ")
        nbChar := len(message)

        line := " "
        for i := 0; i <= nbChar; i++ {
            line += "-"
        }

        fmt.Println(line)
        fmt.Println("< " + message + " >")
        fmt.Println(line)
        fmt.Println("        \\")
        fmt.Println("         \\")

        // Generate a random integer depending on get the number of ascii files
        rand.Seed(time.Now().UnixNano())
        randInt := rand.Intn(getNbOfGopherFiles() - 1)

        // Display random gopher ASCII embed files
        fileData, err := embedGopherFiles.ReadFile("gophers/gopher" + strconv.Itoa(randInt) + ".txt")
        if err != nil {
            log.Fatal("Error during read gopher ascii file", err)
        }
        fmt.Println(string(fileData))
    }
}
それは、説明する時間ですmain() 段階的な機能.
まず、ユーザーが引数なしでアプリケーション/ツールを実行する場合、または- hオプションと“help”オプションを使用すると、使用方法/ヘルプメッセージが表示されます.
    // Display usage/help message
    if len(os.Args) == 1 || (len(os.Args) == 2 && os.Args[1] == "-h") || (len(os.Args) == 2 && os.Args[1] == "--help") {
        usage := "GopherSay is inspired by Cowsay program.\nGopherSay allow you to display a message said by a cute random Gopher.\n\nUsage:\n   gophersay MESSAGE\n\nExample:\n   gophersay hello Gopher lovers"

        fmt.Println(usage)
        return
    }
次に、gophersay 引数を引数としたテキストで、メッセージの文字数を持つすべての引数と変数を取得する変数メッセージを定義します.
私たちは「バブル」で囲まれたこのメッセージを印刷します.
else if len(os.Args) > 1 {

        message := strings.Join(os.Args[1:], " ")
        nbChar := len(message)

        line := " "
        for i := 0; i <= nbChar; i++ {
            line += "-"
        }

        fmt.Println(line)
        fmt.Println("< " + message + " >")
        fmt.Println(line)
        fmt.Println("        \\")
        fmt.Println("         \\")
その後、0と0の間にランダムな整数を生成します.
        // Generate a random integer depending on get the number of ascii files
        rand.Seed(time.Now().UnixNano())
        randInt := rand.Intn(getNbOfGopherFiles() - 1)
…を待つ.なぜ我々は実行するrand.Seed() 機能?rand.Intn(int) [ 0 , n ]で非負の擬似乱数を返します.それはクールだが、それは価値の決定論的なシーケンスを生成する!
だから、“本当の”乱数を持っているために解決策を使用することですrand.Seed() 既定のソースを初期化するには.

我々のコードに戻りましょう、そして、我々は我々のかわいいアスキーGopherを示したいです:
        // Display random gopher ASCII embed files
        fileData, err := embedGopherFiles.ReadFile("gophers/gopher" + strconv.Itoa(randInt) + ".txt")
        if err != nil {
            log.Fatal("Error during read gopher ascii file", err)
        }
        fmt.Println(string(fileData))
そして最後に、ASCII gopher画像ファイルの数を返す関数を作成します.
func getNbOfGopherFiles() int {

    files, err := embedGopherFiles.ReadDir("gophers")
    if err != nil {
        log.Fatal("Error during reading gophers folder", err)
    }

    nbOfFiles := 0
    for _, _ = range files {
        nbOfFiles++
    }

    return nbOfFiles
}

でも、この有名なものは何ですか?
我々だけをパッケージするならばmain.go 実行可能なバイナリでファイルを実行すると、“Gophers/”フォルダがコンピュータに存在しないため、問題が発生します.
Goバージョン1.16の前に、いくつかの解決策がありましたが、新しい embed package .

The new embed package provides access to files embedded in the program during compilation using the new //go:embed directive.


新しい//go:embed ディレクティブは、外部ツールを使用せずに、コンパイル時に静的ファイルやフォルダーをアプリケーションのバイナリに埋め込むことができます.
それを使用するために、最初に、埋め込まれた内容のために変数を宣言しなければなりません.我々の例ではgophers/ フォルダ
//go:embed gophers
var embedGopherFiles embed.FS
次に、このフォルダの1つのファイルを読むことができます.
fileData, err := embedGopherFiles.ReadFile("gophers/gopher" + strconv.Itoa(randInt) + ".txt")
このフォルダのファイルの一覧を取得します.
files, err := embedGopherFiles.ReadDir("gophers")
直接ファイルを埋め込むこともできます.
//go:embed gophers/gopher0.txt
var myFile string
//\embedパターンがフォルダーの場合、全てのファイルが埋め込まれます(再帰的に).または“”.
埋め込む場合は、次のようにフォルダを指定する必要があります.myfolder/*すごい!

テスト!
コード説明の後、それは我々の小さなアプリをテストする時間です!
$ go run main.go
GopherSay is inspired by Cowsay program.
GopherSay allow you to display a message said by a cute random Gopher.

Usage:
   gophersay MESSAGE

Example:
   gophersay hello Gopher lovers
$ go run main.go --help
GopherSay is inspired by Cowsay program.
GopherSay allow you to display a message said by a cute random Gopher.

Usage:
   gophersay MESSAGE

Example:
   gophersay hello Gopher lovers
クール、我々の使用方法のメッセージがあります.
$ go run main.go Hello Gopher lovers!

うん!私たちのテキストは、私たちのかわいいアスキーゲーファーの1つと言われています!

それをビルド!
あなたのアプリケーションは現在準備ができている、あなたはそれを構築することができます.
前の記事ではTaskfile ために我々の共通のタスクを自動化する.
私はTaskfile.yaml ファイル
version: "3"

tasks:
    run: 
        desc: Run the app
        cmds:
        - GOFLAGS=-mod=mod go run main.go

    build:
        desc: Build the app
        cmds:
        - GOFLAGS=-mod=mod go build -o bin/gophersay main.go 

    clean:
        desc: Build the app
        cmds:
        - rm -rf dist 
だから、今我々のアプリを構築することができます:
$ task build
task: [build] GOFLAGS=-mod=mod go build -o bin/gophersay main.go
でも.実行可能なバイナリは私たちの環境、私たちのOS、プラットフォームのためだけであり、私は私の共有したいgophersay 世界的なので、簡単に我々のアプリをコンパイルする方法を見つけるために時間です!

ゴーレム

With GoReleaser , 可能です.
  • プロジェクトのクロスコンパイル
  • github、gitlab、giteaへのリリース
  • Dockerイメージとマニフェストをつくってください
  • パッケージを作成し、homebrewタップ
  • ...
  • ああ、是非、それは正確に何をしたいです!
    第一に、我々はinstall GoReleaser .
    MacOS用
    $ brew install goreleaser/tap/goreleaser
    
    initコマンドを実行して、.goreleaser.yml 設定ファイル:
    $ goreleaser init
       • Generating .goreleaser.yml file
       • config created; please edit accordingly to your needs file=.goreleaser.yml
    
    この新しい生成されたファイルを見ましょう.
    # This is an example .goreleaser.yml file with some sane defaults.
    # Make sure to check the documentation at http://goreleaser.com
    before:
      hooks:
        # You may remove this if you don't use go modules.
        - go mod tidy
        # you may remove this if you don't need go generate
        - go generate ./...
    builds:
      - env:
          - CGO_ENABLED=0
        goos:
          - linux
          - windows
          - darwin
    archives:
      - replacements:
          darwin: Darwin
          linux: Linux
          windows: Windows
          386: i386
          amd64: x86_64
    checksum:
      name_template: 'checksums.txt'
    snapshot:
      name_template: "{{ incpatch .Version }}-next"
    changelog:
      sort: asc
      filters:
        exclude:
          - '^docs:'
          - '^test:'
    
    それはかなりクールです.なぜなら、私たちはgo generate 我々のアプリケーションでは、我々は- go generate ./... 行:-)
    ローカルアプリケーションのリリースを生成するローカルローカルリリースを実行しましょう:
    $ goreleaser release --snapshot --skip-publish --rm-dist
    
    //\これを忘れるなgoreleaser release コマンド--rm-dist オプションまたは実行可能task clean ターゲットdist/フォルダを削除する.そうでなければ、このフォルダが空である必要があるので、あなたは問題を持ちます^^.
    我々が新しいものを調べるならばdist/ 生成されたフォルダは、Goreleaserを生成することがわかります、私たちのために、クロスプラットフォーム実行可能なバイナリ、およびチェックサム:
    dist
    ├── checksums.txt
    ├── config.yaml
    ├── gophersay_0.0.1-next_Darwin_arm64.tar.gz
    ├── gophersay_0.0.1-next_Darwin_x86_64.tar.gz
    ├── gophersay_0.0.1-next_Linux_arm64.tar.gz
    ├── gophersay_0.0.1-next_Linux_i386.tar.gz
    ├── gophersay_0.0.1-next_Linux_x86_64.tar.gz
    ├── gophersay_0.0.1-next_Windows_i386.tar.gz
    ├── gophersay_0.0.1-next_Windows_x86_64.tar.gz
    ├── gophersay_darwin_amd64
    │   └── gophersay
    ├── gophersay_darwin_arm64
    │   └── gophersay
    ├── gophersay_linux_386
    │   └── gophersay
    ├── gophersay_linux_amd64
    │   └── gophersay
    ├── gophersay_linux_arm64
    │   └── gophersay
    ├── gophersay_windows_386
    │   └── gophersay.exe
    └── gophersay_windows_amd64
        └── gophersay.exe
    
    それは完璧です!

    GithubアクションがGoreleaserに会うとき.
    そして何が自動的に新しいリリースを生成するには?
    さて、次のステップはGoreleaserを実行し、GitHub Everytimeの新しい関連リリースを公開することです.私たちのGitリポジトリ内のアプリケーションの新しいバージョンをタグ付けします.
    これをしましょう!
    我々のGit倉庫はGithubでホストされますGitHub Actions 我々のCI(連続統合)パイプラインのために.
    ワークフローを作成します
    $ mkdir .github/workflows
    $ cd .github/workflows
    
    インサイドイットgoreleaser.yml この内容のファイル:
    name: goreleaser
    
    on:
      push:
        tags:
          - '*'
    
    jobs:
      goreleaser:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout
            uses: actions/checkout@v2
            with:
              fetch-depth: 0
          - name: Set up Go
            uses: actions/setup-go@v2
            with:
              go-version: 1.16
          - name: Run GoReleaser
            uses: goreleaser/goreleaser-action@v2
            with:
              distribution: goreleaser
              version: latest
              args: release --rm-dist
            env:
              GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    
    このワークフローは、我々は、倉庫をチェックアウトし、Goreleaserと我々のアプリをパッケージし、Githubリリースを生成する1つのジョブが含まれています.
    //\Githubにリリースするためには、Goreleaserはrepo スコープ.幸いにも、自動的にgithubcreates a GITHUB_TOKEN secret ワークフローで使用する.
    Gitリポジトリで変更をプッシュした後、Gitタグを作成してプッシュします.
    $ git tag -a v1.0.0 -m "First release"
    
    $ git push --tags
    Énumération des objets: 1, fait.
    Décompte des objets: 100% (1/1), fait.
    Écriture des objets: 100% (1/1), 157 octets | 157.00 Kio/s, fait.
    Total 1 (delta 0), réutilisés 0 (delta 0), réutilisés du pack 0
    To https://github.com/scraly/gophersay.git
     * [new tag]         v1.0.0 -> v1.0.0
    
    のgithubリポジトリに行きましょう"Actions" タブを実行し、失敗し、成功したワークフローを監視します.

    完璧な、我々のワークフローは正常にrunned.
    新しいgithubリリースが自動的に作成されました


    だから今、私は私のアプリを更新し、Gitタグを作成し、それをプッシュするたびに、自動的に新しい(github)ghのリリースは、クロスプラットフォームのバイナリで作成されます:-).

    感謝
    あなたがこの記事/チュートリアルとかわいいのが好きならばgophersay アプリケーションは、githubに星を追加することを躊躇しないでください--)

    scraly / gophersay
    Gophersayは、あなたがかわいいランダムなgopherによって言われるメッセージを表示することを許します.
    ゴーペーセイ


    アバウト
    Gophersayで歓迎!
    Gophersayは、カウアイプログラムに触発されます.
    Gophersayは、あなたがかわいいランダムなgopherによって言われるメッセージを表示することを許します.
    インストール
    MacOS用
    brew tap scraly/tools
    brew install gophersay
    
    事前の要件
    インストール1.16バージョンの最小値.
    ビルドのアプリ$ go build -o bin/gophersay main.goor$ task buildアプリを実行する$ ./bin/gophersayor$ task runテストアプリ
    $ ./bin/gophersay Hello Gopher lovers
     ---------------------
    < Hello Gopher lovers! >
     ---------------------
            \
             \
                                              ,
                                 (%..**,,,,,.& .,,.**
                                ,%,*..,,,. .** **.,*,,**./
                               ./*,,.. .**,.,..,.,**.**..(.
                          .   (@.,*%.**.,,**,.,,%*..**,*,/(
                      ,..../../&&%................%///#.,***.....
                       /....,..........................@*@%...,.,
                         .....................................,
                        &*   #@................................
                     &           ...............................
                    #             .........................%       @
                   /@     @,      ........................*          *
                  *.,            @.......................@    /@@
                 /....%        ..........................&
                /........%@@..............................%         %
               ,....................................................*   *   .%
               .........................@,,,,,,,@...................* @   *****#
              *........................@,,,,,,/&(...................  /. ****,**
             ........................@,,,,,,,,,,,, ................/ #/////( ,*,
             //.....................@,,,,,,,,,,,,#................., #//////////
          ...........................,@@@   /  @................../....**//////(
          ...,.........................@@      @.......................///*//*/(
             ...........................&@@@@@@..................   @///////////
             ,..................................................*   @///////&* *
             /..................................................    @/@..,(@.& (
             ,.................................................     @ @/ .(#   .
              ................................................,     @ ,.%(#,**
              .............................................../      @ . @////*/

    View on GitHub

    結論
    あなたがこの記事と前の記事で見たように、Goで複数の異なるアプリケーションを作成することは可能です.そしてビルドを自動化し、コンパイルをクロスします.
    今回はコブラやバイパーや他のフレームワークを使用していませんでした.
    GoHelsayアプリケーションのすべてのコードは、次のとおりです.https://github.com/scraly/gophersay
    次の記事では、我々は他の種類を作成します/アプリケーションのタイプでGO.
    閉じるこの動画はお気に入りから削除されています.