20200910のGoに関する記事は5件です。

goreleaserをGithub Actionsで利用するまでのQuick Start

goreleaserは、Goプロジェクトをビルドして、各OS向けの実行可能バイナリやDocker Imageを作成し、GithubのReleaseやDocker Repositoryに配布してくれるツールです。この記事ではGithub Actionsを利用して、goreleaserによるビルドから配布までを自動化するまでの手順を示します。

1) goreleaserのインストール

次のURLを参考にgoreleaserをインストールし、goreleaserコマンドを利用できる環境にします: https://goreleaser.com/install/

個人的には公式のDockerイメージを使うのが一番楽かと思います。

2) .goreleaser.ymlの作成

プロジェクトディレクトリの直下にgoreleaser.ymlを作成します。作成にはgoreleaser initコマンドを利用します。

cd project-directory
goreleaser init

goreleaserのインストールにDockerを利用した場合は、次のようにしてください。

cd project-directory
docker run --rm --privileged \
  -v $PWD:/src \
  -w /src \
  goreleaser/goreleaser init

3) .goreleaser.ymlの修正

必要な場合は.goreleaser.ymlを修正してください。もっとも作成した初期の状態でも、windows、Linux、OSX向けの実行可能バイナリを作成してくれる状況にはなっています。

4) ワークフローファイルの作成

Github Actionsでgoreleaserを利用する場合は公式のワークフローを利用するのがもっとも便利です。プロジェクトディレクトリ直下に.github/workflowsディレクトリを作成し、任意の名前の.ymlファイルを作成します。この.ymlファイルの中身は以下のURLのREADME.md > Usage > Workflowをそのままコピペすればよいです: https://github.com/goreleaser/goreleaser-action

5) ワークフローファイルの修正

必要な場合は、ワークフローファイルを修正してください。

6) ワークフローの起動

あとはワークフローファイルに書かれた条件を実現して、Github Actionsを起動するだけです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Go言語で kintoneアプリのフィールド情報をCSV出力するコマンドラインツールを作った話し

Go言語の自習の仕上げに、yaclik という小さなコマンドラインツールを作ったのでその紹介です。

kintoneアプリからレコードを取得・登録などを行う、Go言語で書かれたコマンドラインツールに、cli-kintoneがあります。

https://github.com/kintone/cli-kintone

今回試しに作ったのは、kintoneアプリのフィールド情報をAPIで取得して、CSV形式でターミナルに表示するだけのツールです。
それ以上のことは何も出来ないのですが:sweat_smile:、kintoneアプリのフィールド一覧がドキュメントで必要になった時には使えるかと思います。

出力できる情報は下記の3つだけです。

  1. フィールドコード
  2. フィールド名称
  3. フィールドタイプ

一応テーブル内のフィールドにも対応していますが、その際のフィールドコードにプレフィックスとして

~SUBTABLE~<フィールドコード> のように表示します。

必要に応じて、CSVファイルに出力した後に編集ください。:bow_tone1:

ファイルは下記に置いてあります。

https://github.com/sy250/yaclik

ビルドしたバイナリファイルもリリースにアップしていますが、Mac版のみです。

Windowsで試されたい方はソースからビルドいただければと思います。

使い方

Macの場合です。

下記からバイナリファイルをダウンロードします
https://github.com/sy250/yaclik/releases

適当なディレクトリにて実行します。
./yaclik -hでコマンドライン引数を表示します。

Usage of ./yaclik:
  -a string
        App ID (default "0")
  -d string
        Domain name
  -n string
        User login name
  -o string
        Output format (default "csv")
  -p string
        User login password

-o jsonでJSON形式で出力します。

出力サンプル

kintoneの顧客サポートパックにある、問い合わせ管理アプリの情報を出力しています。

$ yaclik -a <APP_ID> -d <SUB_DOMAIN> -n <USER_ID> -p <USER_PASSWORD>
field_code,label,type
レコード番号,レコード番号,RECORD_NUMBER
更新日時,更新日時,UPDATED_TIME
カテゴリー,カテゴリー,CATEGORY
対応詳細,対応詳細,SUBTABLE
~SUBTABLE~対応内容,対応内容,MULTI_LINE_TEXT
~SUBTABLE~添付ファイル,添付ファイル,FILE
~SUBTABLE~対応日時,対応日時,DATETIME
電話番号,電話番号,LINK
作成日時,作成日時,CREATED_TIME
ご担当者名,ご担当者名,SINGLE_LINE_TEXT
詳細,詳細,MULTI_LINE_TEXT
更新者,更新者,MODIFIER
作成者,作成者,CREATOR
問い合わせ種別,問合せ種別,RADIO_BUTTON
ステータス,ステータス,STATUS
対応状況,対応状況,DROP_DOWN
受付日時,受付日時,DATETIME
対応担当者,対応担当者,USER_SELECT
期限,期限,DATE
作業者,作業者,STATUS_ASSIGNEE
ルックアップ,会社名,SINGLE_LINE_TEXT

少し便利な使い方

Macでは、引数を別のシェルスクリプトにしてあげたり、作成するファイル名もファイルに一覧として登録すると便利だと思います。

出力するファイル名の一覧として下記を用意

1-顧客台帳.csv
2-問い合わせ管理.csv

ドメインやログイン情報として下記を用意

env.sh
export DOMAIN=<サブドメイン>
export APP_ID=<ログインID>
export PASSWORD=<パスワード>
bat.bash
for file in `cat list`
do
  echo "$file"
  [[ ${file} =~ ^([0-9]+)-(.*)$ ]];
  app=${BASH_REMATCH[1]}
  ./yaclik -a ${app} -d $DOMAIN -n $APP_ID -p $PASSWORD | nkf -Ws > ${file}
done
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Go言語で作るDiscordBot(開発環境・クイックスタート・デプロイ・機能集を解説!)

discordgoでdiscordbotを作っているので、開発環境・クイックスタート・デプロイ・機能集の説明をしたいと思います。

  • 9/10 開発環境に関する記事作成
  • 9/15 クイックスタートを作成
  • 9/16 herokuでの立ち上げ方
  • 9/16 GuildName & GetMessageの機能を追加!

開発環境

筆者はMacユーザーですのでWindowsは書きませんでした。

エディイター Goland

環境準備がPath設定ぐらいなのですごく楽です!
Goland Official Web Page

discordgo インストール

go get github.com/bwmarrin/discordgo

Github: https://github.com/bwmarrin/discordgo
ドキュメント: https://pkg.go.dev/github.com/bwmarrin/discordgo?tab=doc

Modules の機能

Modules は、依存モジュール管理ツールです。
Go言語 1.11 から標準で使えるようになりました。
以下のような機能を持っています。

  • 依存モジュールの自動検知
  • 依存モジュールのバージョン固定、バージョンアップ検知

依存モジュールの情報は go.mod と go.sum という名前のファイルに記載されます。
これらのファイルを git などでバージョン管理することによって、依存モジュールとそのバージョンを明確にすることができます。

参考サイト: https://blog.mmmcorp.co.jp/blog/2019/10/10/go-mod/

Botアカウントの作成と登録

Discord Developer PortalでBotアカウントを作成し、Discordサーバーに登録しましょう。
アクセストークンも必要なので取得してください。

詳細な手順はこちらの記事にて紹介しています。
Discord Botアカウント初期設定ガイド for Developer - Qiita

GitHubアカウントを作成とリポジトリ作成

Github のアカウントを作ってソースコードなどの管理をします。
アカウントが作成できたら 「New repository」 があるので新しいリポジトリを作りましょう。
スクリーンショット 2020-09-15 19.33.40.png

下のような画面が表示されたらリポジトリの設定をしましょう。

  • リポジトリ名 : demoapp-< username >  など
  • 公開設定 : 間違ってトークンなどをPushしても大丈夫なようにプライベートをおすすめします!
  • READMEの生成 : 今回は必要ありません
  • gitignoreの生成 : チェックしてください、するとテンプレート選択が出ますので、「Go」と検索してGoを選んでください
  • Licenseの生成: 今回は必要ありません

スクリーンショット 2020-09-15 19.38.28.png

Repository Clone

先ほど作成したリポジトリをローカルにクローンして開発できるようにしましょう!
以下のコマンドを実行するとディレクトリが作成されます。

git clone <repository-url>

クイックスタート(ローカルバージョン)

1. 環境変数ファイルを作成

touchコマンドでenvファイルを作ります。

touch .env

環境変数に先ほど作成したDiscord BotのTokenを設定します。
作っていない方は開発環境の説明に戻ってください。

DISCORD_TOKEN=<Token>

2. Main.goを作成して動かす

touchコマンドでmain.goを作成します。

touch main.go

main.goを書いていきます。
機能内容
- カスタムステータスを設定して「demoapp!」と表示させることもできます。
- ユーザーが「ServerName」とチャットをするとサーバー名を変えてくれます
- ユーザーが「!Hello」とチャットをすると「Hello」と返事を返してくれます

環境変数を取得するために以下のライブラリをダウンロードする必要があります。

go get github.com/joho/godotenv
package main

import (
    "fmt"
    "log"
    "os"
    "os/signal"
    "syscall"

    "github.com/joho/godotenv"
    "github.com/bwmarrin/discordgo"
)

func main() {
    /*local only code */
    err := godotenv.Load(fmt.Sprintf("./%s.env", os.Getenv("GO_ENV")))
    if err != nil {
        // .env読めなかった場合の処理
        log.Fatal(err)
    }

    Token := os.Getenv("DISCORD_TOKEN")
    log.Println("Token: ",Token)
    if Token == "" {
        return
    }

    // Create a new Discord session using the provided bot token.
    dg, err := discordgo.New("Bot " + Token)
    if err != nil {
        fmt.Println("error creating Discord session,", err)
        return
    }

    // Register ready as a callback for the ready events.
    dg.AddHandler(ready)

    // Register the messageCreate func as a callback for MessageCreate events.
    dg.AddHandler(messageCreate)

    // In this example, we only care about receiving message events.
    dg.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsGuilds | discordgo.IntentsGuildMessages)

    // Open a websocket connection to Discord and begin listening.
    err = dg.Open()
    if err != nil {
        fmt.Println("error opening connection,", err)
        return
    }

    // Wait here until CTRL-C or other term signal is received.
    fmt.Println("Bot is now running.  Press CTRL-C to exit.")
    sc := make(chan os.Signal, 1)
    signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
    <-sc

    // Cleanly close down the Discord session.
    dg.Close()
}

// This function will be called (due to AddHandler above) when the bot receives
// the "ready" event from Discord.
func ready(s *discordgo.Session, event *discordgo.Ready)  {
    // Set the playing status.
    log.Println("BotName: ",event.User.ID)
    log.Println("BotID: ",event.User.Username)
    s.UpdateStatus(0, "demoapp!")
}


// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the authenticated bot has access to.
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {

    // Ignore all messages created by the bot itself
    // This isn't required in this specific example but it's a good practice.
    // ボットからのメッセージの場合は返さないように判定します。
    if m.Author.ID == s.State.User.ID {
        return
    }

    // Server名を取得して返します。
    if m.Content == "ServerName" {
        g, err := s.Guild(m.GuildID)
        if err != nil {
            log.Fatal(err)
        }
        log.Println(g.Name)
        s.ChannelMessageSend(m.ChannelID, g.Name)
    }

    // !Helloというチャットがきたら 「Hello」 と返します
    if m.Content == "!Hello" {
        s.ChannelMessageSend(m.ChannelID, "Hello")
    }
}

書き終わりましたら、以下のコマンドを実行してボットを起動しましょう!

go run main.go

Herokuデプロイ

Procfileを作成

Heroku アプリでは、「Procfile」と呼ばれる設定ファイルを 1 つだけ使用してアプリの実行に必要なプロセスタイプを指定します

$echo 'worker: bin/demoapp-< username>' > Procfile

go.modに依存関係を追加

依存関係をgo.modに書き込みます!
実行後にcat go.modを実行してみて追加されているか確認してみるのもいいかもしれません。

go build

gitignoreの修正

リポジトリ生成時に自動で生成されたgitignoreファイルは書き足す必要があります。

# Created by https://www.toptal.com/developers/gitignore/api/go
# Edit at https://www.toptal.com/developers/gitignore?templates=go

### Go ###
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

### Go Patch ###
/vendor/
/Godeps/

# End of https://www.toptal.com/developers/gitignore/api/go

# Golandを使用している場合は.ideaファイルは対象外にしましょう。
.idea <-- 追加 
# Tokenキーなどは公開するのは良くないので対象外にしましょう。
.env <-- 追加

Push

Pushの準備ができたのでプッシュしましょう。

git add -A .

git commit -m "first commit"

git push 

これでリポジトリにファイルが増えて更新されたと思われます。

herokuにデプロイ

アプリを作成

  • 「Create New App」でアプリを作成します。
  • 「app-name」はご自由で構いません。
  • 「Choose a region」はアメリカで

スクリーンショット 2020-09-16 3.45.04.png

Githubリポジトリをherokuにconnect

  • 「Deployment method」はGitHubを選択してください
  • 「Connect to GitHub」デプロイするリポジトリをconnectしましょう! スクリーンショット 2020-09-16 3.49.04.png

herokuの設定

Settingsの画面に移動します。

  • 「Config Vars」の「Reveal Config Vars」をクリックして入力欄が表示されます。Keyにはクイックスタートで設定した「DISCORD_TOKEN」を設定します。ValueにはTokenを設定します。

  • 「Buildpacks」では、Goと検索して「heroku/go」を追加しましょう!

スクリーンショット 2020-09-16 3.56.32.png

デプロイ

  • 「Automatic deploys」は「Enable Automatic Deploys」と書かれているボタンを押しましょう!
  • 「Manual deploy」の「Deploy Branch」を押すとデプロイと実行が行われます。

デプロイが成功したらDiscordbotは制限がかからない限りオンライン状態でいられます!

スクリーンショット 2020-09-16 3.52.58.png

機能集

例えばサーバーの名前GuildNameの取得などのコードの書き方を説明します。

メッセージを取得

特にチャンネル指定で受け取るメッセージではなく全体からのメッセージに対応します。
さらにボット同士の無限やりとりが起きないようにボットからの受け取りには反応しないようにします。

func messageCreate(s *discordgo.Sesstion, m *discordgo.MessageCreate) {
    if m.Author.ID == s.State.User.ID {
        return 
    }

    if m.Content == "Hello!" {
        s.ChannelMessageSend(m.ChannelID, "Hello")
    }
}

GuildName

GuildのGuildNameを取得します。

func messageCreate(s *discordgo.Sesstion, m *discordgo.MessageCreate) {
    if m.Content == "ServerName" {
        g, err := s.Guild(m.GuildID)
        if err != nil {
            log.Fatal(err)
        }
        s.ChannnelMessageSend(m.ChannelID, g.Name)
    }
}

最後

書いている人はGo歴一ヶ月半なので正しい立ち上げ方がありましたらコメントなどで教えてください!
heroku以外の立ち上げ方や機能ごとの書き方など学び次第追加したいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

毎回go.modとmain.goを作るのがめんどくさい

コマンドで生成すればよかった

gogen.go

package main

import (
    "io/ioutil"
    "log"
)

func main() {
    if err := ioutil.WriteFile("go.mod", []byte("module sample"), 0755); err != nil {
        log.Fatal(err)
    }
    if err := ioutil.WriteFile("main.go", []byte("package main\r\n\r\nimport \"fmt\"\r\n\r\nfunc main() {\r\n    fmt.Println(\"Hello World\")\r\n}\r\n"), 0755); err != nil {
        log.Fatal(err)
    }
}

実現方法

  • 適当なディレクトリを作成する
  • そこにgogen.goを作る
  • 上記のコードをgogen.goにはっつける
  • go install gogen.go

使い方

Go書き始めたい時に空ディレクトリ作る
そこの階層でコマンドプロンプト開いて下記を実行
gogen
go.modとmain.goが作られる

※動かない環境もあるかもしれない
※モジュール名はsample固定

あとがき

サクッと書き始めたい時に割とめんどうだったりするので作った。
なんで今まで気付かなかったんだろう・・・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Go】sqlxでBulk Insert

概要

以下のようなテーブルがあるとします。

user
 - id
 - name

userテーブルに対して、以下のように複数のValueを一度にinsertをしたい。

INSERT INTO user (name)
VALUES ('tom'),('james'),('piyo'),('alex'),('josh');

上記をsqlxで実現する方法

実装

NamedExecを使って、以下のように実装する

import (
  "database/sql"
  "fmt"

  _ "github.com/lib/pq"
  "github.com/jmoiron/sqlx"
)

type User struct {
  ID int32 `db:"id"`
  Name string `db:"name"`
}

func main() {
  db, _ := sql.Open("postgres","user=postgres password=pw dbname=postgres sslmode=disable")

  userNames []string{"tom", "james", "piyo", "alex", "josh"}
  users := make([]User, len(userNames))
  for i, v := range users {
    users[i] = User{
      Name: v,
    }
  }

  query := `INSERT INTO user (name) VALUES (:name)`
  _, err := db.NamedExec(query, users)
  if err != nil {
    fmt.Println("エラーだよ")
  }
}


  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む