- 投稿日:2019-06-07T23:04:54+09:00
go言語でSlackに投稿する
環境
go 1.12.5
コード
userName
/webhookUrl
/iconUrl
は適宜調整してね。type SlackMessage struct { Text string `json:"text"` Channel string `json:"channel"` Username string `json:"username"` IconEmoji string `json:"icon_emoji"` IconUrl string `json:"icon_url"` Attachments *[]*SlackMessageAttachment `json:"attachments"` } type SlackMessageAttachment struct { Fallback string `json:"fallback"` Color string `json:"color"` Pretext string `json:"pretext"` AuthorName string `json:"author_name"` AuthorLink string `json:"author_link"` AuthorIcon string `json:"author_icon"` Title string `json:"title"` Text string `json:"text"` Fields *[]*SlackMessageAttachmentField `json:"fields"` ImageUrl string `json:"image_url"` ThumbUrl string `json:"thumb_url"` Footer string `json:"footer"` FooterIcon string `json:"footer_icon"` TimeStamp int64 `json:"ts"` } type SlackMessageAttachmentField struct { Title string `json:"title"` Value string `json:"value"` Short bool `json:"short"` } func NotifySlack(channel string, message string, attachments *[]*SlackMessageAttachment) { userName := "Admin Client" webhookUrl := "https://hooks.slack.com/services/abc/def/ghi" iconUrl := "https://example.com/icon.png" params, _ := json.Marshal(SlackMessage{ message, channel, userName, "", iconUrl, attachments, }) resp, _ := http.PostForm( webhookUrl, url.Values{"payload": {string(params)}}, ) ioutil.ReadAll(resp.Body) defer resp.Body.Close() }つかいかた
func Test() { attachment := &SlackMessageAttachment{ "フォールバックメッセージだよ", "#00ff00", "プレテキストだよ", "著者だよ", "https://www.google.com/", "https://img.icons8.com/metro/420/email.png", "タイトルだよ", "せつめーだよ", nil, "https://upload.wikimedia.org/wikipedia/en/thumb/e/e0/WPVG_icon_2016.svg/1024px-WPVG_icon_2016.svg.png", "https://developer.android.com/guide/practices/ui_guidelines/images/NB_Icon_Mask_Shapes_Ext_02.gif?hl=ja", "フッターだよ", "https://image.flaticon.com/icons/png/512/33/33447.png", 0, } fields := make([]*SlackMessageAttachmentField, 0) fields = append(fields, &SlackMessageAttachmentField{ "あいうえお", "かきくけこ", true, }) fields = append(fields, &SlackMessageAttachmentField{ "さしすせそ", "たちつてと", true, }) fields = append(fields, &SlackMessageAttachmentField{ "長いテキスト", "みなみあそみずのうまれるさとはくすいこうげん", false, }) fields = append(fields, &SlackMessageAttachmentField{ "長いテキスト", "Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch", false, }) attachment.Fields = &fields NotifySlack("#channel_name", "", &[]*SlackMessageAttachment{attachment}) }結果
所感
構造体作るの面倒くさい。
- 投稿日:2019-06-07T18:47:10+09:00
Go言語の勉強に役立つリンク集(Qiita Only)
※随時更新して行きます。
チートシート的なやつ
とりあえず手っ取り早く全体像掴めみたいときや、辞書的な感じで使えるいい感じの記事。
golang チートシート - Qiita
Go言語:文法基礎まとめ - Qiitaポインタ
Interface
インタフェースの実装パターン #golang - Qiita
構造体
Goを学びたての人が誤解しがちなtypeと構造体について #golang - Qiita
メソッド
メソッドとレシーバについてのまとめ #golang - Qiita
デバッグ
go言語のデバッガ(delveとgdb)とcore dump - Qiita
SQL
[Go言語] database/sqlパッケージを使ってみた - Qiita
ORM
ダックタイピング
- 投稿日:2019-06-07T18:47:10+09:00
Go言語のブックマーク
※随時更新して行きます。
チートシート的なやつ
とりあえず手っ取り早く全体像掴めみたいときや、辞書的な感じで使えるいい感じの記事。
関数
配列とスライス
Goのarrayとsliceを理解するときがきた - Qiita
ポインタ
Interface
インタフェースの実装パターン #golang - Qiita
構造体
Goを学びたての人が誤解しがちなtypeと構造体について #golang - Qiita
メソッド
メソッドとレシーバについてのまとめ #golang - Qiita
エラーハンドリング
- Go言語のエラーハンドリングについて - Qiita
- Golangのエラー処理とpkg/errors | SOTA
- Wrap(err) in our production #golang | Wantedly Engineer Blog
デバッグ
go言語のデバッガ(delveとgdb)とcore dump - Qiita
SQL
[Go言語] database/sqlパッケージを使ってみた - Qiita
DynamoDB
ORM
YAML
Swagger
[swaggo]GoのGoDocを書いたら、Swaggerを出せるやばいやつ - Qiita
パッケージ管理
Git
Docker
静的解析ツール
無料で使える Go 言語の CI サービス『GolangCI』を使ってみる | DevelopersIO
ダックタイピング
gRPC
- Goで始めるgRPC入門 - Qiita
- 初めてのgRPC / Starting gRPC - Speaker Deck
- goのgRPCで便利ツールを使う - Qiita
- microservicesはじめました (1) - 朝日ネット 技術者ブログ
モック
Go Mockでインタフェースのモックを作ってテストする #golang - Qiita
タスクランナー
- 投稿日:2019-06-07T18:47:10+09:00
Go言語の勉強に役立つブックマーク集
※随時更新して行きます。
チートシート的なやつ
とりあえず手っ取り早く全体像掴めみたいときや、辞書的な感じで使えるいい感じの記事。
golang チートシート - Qiita
Go言語:文法基礎まとめ - Qiita関数
配列とスライス
Goのarrayとsliceを理解するときがきた - Qiita
ポインタ
Interface
インタフェースの実装パターン #golang - Qiita
構造体
Goを学びたての人が誤解しがちなtypeと構造体について #golang - Qiita
メソッド
メソッドとレシーバについてのまとめ #golang - Qiita
デバッグ
go言語のデバッガ(delveとgdb)とcore dump - Qiita
SQL
[Go言語] database/sqlパッケージを使ってみた - Qiita
DynamoDB
ORM
パッケージ管理
ダックタイピング
- 投稿日:2019-06-07T18:47:10+09:00
Go言語の学習に役立つブックマーク集
※随時更新して行きます。
チートシート的なやつ
とりあえず手っ取り早く全体像掴めみたいときや、辞書的な感じで使えるいい感じの記事。
関数
配列とスライス
Goのarrayとsliceを理解するときがきた - Qiita
ポインタ
Interface
インタフェースの実装パターン #golang - Qiita
構造体
Goを学びたての人が誤解しがちなtypeと構造体について #golang - Qiita
メソッド
メソッドとレシーバについてのまとめ #golang - Qiita
エラーハンドリング
- Go言語のエラーハンドリングについて - Qiita
- Golangのエラー処理とpkg/errors | SOTA
- Wrap(err) in our production #golang | Wantedly Engineer Blog
デバッグ
go言語のデバッガ(delveとgdb)とcore dump - Qiita
SQL
[Go言語] database/sqlパッケージを使ってみた - Qiita
DynamoDB
ORM
YAML
Swagger
[swaggo]GoのGoDocを書いたら、Swaggerを出せるやばいやつ - Qiita
パッケージ管理
Git
Docker
静的解析ツール
無料で使える Go 言語の CI サービス『GolangCI』を使ってみる | DevelopersIO
ダックタイピング
gRPC
microservicesはじめました (1) - 朝日ネット 技術者ブログ
モック
Go Mockでインタフェースのモックを作ってテストする #golang - Qiita
タスクランナー
- 投稿日:2019-06-07T16:26:32+09:00
Goスタック模索メモ
HTTP Server
Router
gorilla/mux: A powerful URL router and dispatcher for golang.
https://github.com/gorilla/mux定番。薄い。
go-chi/chi: lightweight, idiomatic and composable router for building Go HTTP services
https://github.com/go-chi/chi薄い。gorilla/muxよりAPIが直感的。
JSON Request
小さいので自前で書く人が多いっぽい
以下などに薄い実装
render/decoder.go at master · go-chi/render
https://github.com/go-chi/render/blob/master/decoder.goRender
unrolled/render: Go package for easily rendering JSON, XML, binary data, and HTML templates responses.
https://github.com/unrolled/render人気っぽい
Job Queue
RichardKnop/machinery: Machinery is an asynchronous task queue/job queue based on distributed message passing.
https://github.com/RichardKnop/machineryBroker、ストアそれぞれのバックエンドがいろいろ対応してる(ex. AMQP, Redis, SQS, GCP Pub/Sub, Memcache, MongoDB)
DelayもRetryも対応してるgocraft/work: Process background jobs in Go
https://github.com/gocraft/workRedisバックエンド。Delayも対応してる。
RDBMS
jinzhu/gorm: The fantastic ORM library for Golang, aims to be developer friendly
https://github.com/jinzhu/gorm人気。ORM。
go-gorp/gorp: Go Relational Persistence - an ORM-ish library for Go
https://github.com/go-gorp/gorp人気。Select文は自分でSQL書いてstructへのマッピングはやってくれる。
クエリをコントロールしたい場合によさそう。Development
oxequa/realize: Realize is the #1 Golang Task Runner which enhance your workflow by automating the most common tasks and using the best performing Golang live reloading.
https://github.com/oxequa/realizeホットリロード
go mod使ってる & cmdディレクトリにmainがあるときに相対モジュールが解決できないエラーが起きる(条件は合っていないかも)が、以下にある設定で一応解決する。Realize が Go 1.11 の Modules で使えない - Qiita
https://qiita.com/enta0701/items/0d0592abb18a333b3268
- 投稿日:2019-06-07T15:07:53+09:00
Goのスコープに苦しんだ事例集
コンパイル通るけどtestで死ぬ事例、個人的No.1のスコープ関連についてまとめ。
事例その1 メソッド完結
メソッド内でスコープ切れちゃうので、メソッド内でnewしてもダメだぜの例。
"スコープが切れる"という表現でいいのだろうか。。。type hogehoge map[string]string func (h hogehoge) Seter(p string) { h["key"] = p } func (h *hogehoge) NewSeter(p string) { h = &hogehoge{"p": p} } func main() { f := hogehoge{} f.Seter("ddd") fmt.Println(f) // <- map[key:ddd] f.NewSeter("sss") fmt.Println(f) // <- map[key:ddd] }https://play.golang.org/p/mCEUyNGLgsy
そもそも、こういうことがやりたかったのでコード間違ってたんですけどね。
事例その2 ループ内部完結
=
と:=
を間違える、よくやるやつ。dev := "hoge" for _, v := range []string{"a", "b"} { dev := v fmt.Println(dev) // <- "a","b" } fmt.Println(dev) // <- "hoge"
- 投稿日:2019-06-07T12:32:36+09:00
Goといえばチャネルでしょ!!! 第3弾
第三弾?
前回のやつはこれ
Goroutineを触った。
今回はタイトル通りチャネルを触っていこうと思うchannelとは
並列処理を行った結果を呼び出し先の関数に返すことが出来る。
前回のモノで戻り値を返そうとするとエラーが起きるコード
package main import "fmt" func channel(s []int,c chan int){ sum:=0 for i:=0;i<5;i++ { sum += s[i] } c <- sum } func main(){ s := []int{1,2,3,4,5} c := make(chan int) go channel(s,c) r := <-c fmt.Println(r) }解説
func main()
- 1~5の数字の入ったスライスを作りこれをsで宣言する
- そしてmakeでchan intで戻り値の値を設定しチャネルとしてcを宣言する
- そして並列処理のためにgoを記入し、引数にスライスとチャネルを入れる
- Go to channel
- そしてchannelからcが送られてきたのでrで受け取る。
func channel()
- 並列処理によりスレッドぐ作られ、この関数がスタートする
- 引数のスライスを足していき結果をcのチャネルに送信する。
- その時の記号は <- である。
最後に
解説が見にくくなってしまった許してください。
次回はBuffer channelでーす。
- 投稿日:2019-06-07T10:45:57+09:00
xerrorsパッケージでラップしたエラーをswitchで判別する #golang
TL;DR
switchの条件式を
xerrors.Unwrap(err).(type)
にする。問題
xerrors.Errorf
でラップしたエラーをerrors.Cause(err).(type)
で条件分岐させようとしたが、defaultに振り分けられてしまった。err := xerrors.Errorf("my error: %w", &MyError{}) switch errors.Cause(err).(type) { case *MyError: fmt.Println("my error") default: fmt.Println("other") } //-> other解決方法
試行錯誤した結果、switchの条件式を
xerrors.Unwrap(err).(type)
にすることで目的の処理をさせることができた。err := xerrors.Errorf("my error: %w", &MyError{}) switch xerrors.Unwrap(err).(type) { case *MyError: fmt.Println("my error") default: fmt.Println("other") } //-> my errorおまけ
ラップしたエラーを取り出すときは
xerrors.As
を使う。switch xerrors.Unwrap(err).(type) { case *MyError: var e *MyError xerrors.As(err, &e) fmt.Printf("%v\n", e) default: fmt.Println("other") }リンク
- 投稿日:2019-06-07T09:52:52+09:00
ojichatをSlackに流す
最近ojichatが流行ってますね。
普段会社の勤怠はSlackに投稿してるんですが、あまりに自分の遅刻が多く自分のメッセージで埋まるので、ojichatを流すことにしました。https://github.com/naomichi-y/ojichat-slack-bot
和む。
- 投稿日:2019-06-07T09:08:28+09:00
[Go初心者]map
func main() { m := map[string]int{"apple": 100, "banana": 200} //map[apple:100 banana:200] fmt.Println(m) fmt.Println(m["apple"]) //100 m["banana"] = 300 fmt.Println(m) //map[apple:100 banana:300] m["orange"] = 500 fmt.Println(m) //map[apple:100 banana:300 orange:500] fmt.Println(m["nothing"]) //0 intのデフォルト値 v, ok := m["apple"] //okは中身が入っているかチェックするもの。2つ目の返り値はなくても良い fmt.Println(v, ok) //100 true v2, ok2 := m["nothing"] fmt.Println(v2, ok2) //0 false m2 := make(map[string]int) m2["sp"] = 20000 fmt.Println(m2) //メモリ上に空のマップをつくってから値を代入した /* var m3 map[string]int m3["sp"] = 50000 fmt.Println(m3) //panic: assignment to entry in nil map //宣言はしているがメモリ上に入れるマップがないのでエラー */ var s []int if s == nil { fmt.Println("NIL") } //varで宣言した場合は、mapもスライスもnil }【参考】
現役シリコンバレーエンジニアが教えるGo入門(https://www.udemy.com/share/100BhMB0obeFpbTX4=/)
- 投稿日:2019-06-07T08:10:22+09:00
Lambda(Golang)でAPI Gatewayのクエリ文字列を使用する
はじめに
Lambda(Golang)でAPI Gatewayのクエリ文字列を使用する方法がなかなか見つからなかったので備忘録としてまとめます。
デモ
https://rjt8xm2a63.execute-api.ap-northeast-1.amazonaws.com/dev/hello?name=Naoki
{"message":"Hello, Naoki"}
TL;DR
- Lambdaのハンドラーの第2引数で
request events.APIGatewayProxyRequest
を受け取るq := request.QueryStringParameters
でクエリ文字列のMapを返すサンプルコード
https://github.com/oke-py/qs-demo
Serverless Frameworkを利用してデプロイする前提とします。serverless.ymlservice: qs-demo frameworkVersion: ">=1.28.0 <2.0.0" provider: name: aws runtime: go1.x # you can overwrite defaults here stage: dev region: ap-northeast-1 # you can add statements to the Lambda function's IAM Role here iamRoleStatements: - Effect: "Allow" Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" Resource: "arn:aws:logs:*:*:*" package: exclude: - ./** include: - ./bin/** functions: hello: handler: bin/hello events: - http: path: hello method: get request: parameters: querystrings: # クエリ文字列が必須ならtrue、必須でなければfalse name: truehello/main.gopackage main import ( "bytes" "context" "encoding/json" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) // Response is of type APIGatewayProxyResponse since we're leveraging the // AWS Lambda Proxy Request functionality (default behavior) // // https://serverless.com/framework/docs/providers/aws/events/apigateway/#lambda-proxy-integration type Response events.APIGatewayProxyResponse // Handler is our lambda handler invoked by the `lambda.Start` function call func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (Response, error) { q := request.QueryStringParameters name := q["name"] var buf bytes.Buffer body, err := json.Marshal(map[string]interface{}{ "message": "Hello, " + name, }) if err != nil { return Response{StatusCode: 404}, err } json.HTMLEscape(&buf, body) resp := Response{ StatusCode: 200, IsBase64Encoded: false, Body: buf.String(), Headers: map[string]string{ "Content-Type": "application/json", "X-MyCompany-Func-Reply": "hello-handler", }, } return resp, nil } func main() { lambda.Start(Handler) }まとめ
無事、Lambda(Golang)でAPI Gatewayのクエリ文字列を使用することができました。
参考
- 投稿日:2019-06-07T01:26:36+09:00
yamlから欲しい情報をGoでとる(マイグレーションツールを使うときに使うファイルを流用する)
動機
migrationツールを使うと次のようなdb.confを書いたりします。
development: dialect: mysql dir: db/migrations datasource: user:password@tcp(db:3306)/db_name?charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true production: dialect: postgres dir: migrations/postgres datasource: dbname=myapp sslmode=disable table: migrationsせっかくなら、普通のデータベース接続もこのYAMLからデータを取ってきたい!取ってきたくない?
go-yamlを使って簡単に()実装できます!
実装例
buf, err := ioutil.ReadFile("file.pass") if err != nil { log.Fatal(err) return } m := make(map[interface{}]interface{}) err = yaml.Unmarshal(buf, &m) if err != nil { log.Fatal(err) panic(err) } fmt.Printf("%d\n", m["development"].(map[interface {}]interface {})["datasource"]) db_config :=m["development"].(map[interface {}]interface {})["datasource"].(string) db, err := dbr.Open("mysql", db_config , nil)忘備録だけど、ここに行きつくのにどちゃくそ時間がかかった……
Goのインターフェースよくわからん。ちなみにdbrを接続用のツールに使っています。参考
https://qiita.com/umanoda/items/07887d33ef1155b26ed2
https://ota42y.com/blog/2014/11/13/go-yaml/
https://qiita.com/daiching/items/a384a5ce229cf714a3b5
- 投稿日:2019-06-07T00:01:55+09:00
goで atcoder の入力例実行の手間を省くツールを作った
このページについて
atcoderの入力例をすべて取得し、指定された実行スクリプトに標準出力として渡すツールについて紹介しています
ex.) 実行例
実物は、okだったら緑、errorだったら赤でプリントされます$ acc atcoder -u https://atcoder.jp/contests/abc119/tasks/abc119_b -c "go run ./main.go" start atcoder test v0.0.0-5780f7c (built with go1.12.1) Case [0] exp: 48000.0 ok! Case [1] exp: 138000000.0038 ok!背景
atcoder の入力例をいちいちfileにコピペして下記のようにコマンド叩いていましたが
さすがに面倒になってきたので作ってみました$ cat file | go run main.go内容
設計思想
- サイトに迷惑をかけない
- 最初の一回リクエストしたあとは、cacheを残してそこから取得するようにしました
- $GOPATH/bin にdbが作られます
使い方
$ go get -u github.com/smith-30/accインストールしたらあとはatcoderの問題ページのurlと
テストケースを流したいスクリプトを渡すだけです$ acc atcoder -u http://atcoder.jp/<problem path> -c "go run path/to/main.go"ライブラリなど
その他
いろんなテストケースと予想されている出力パターンがあると思いますが
全てに対応しているかはわかりません。うまく使えないとかあればissueお願いします
よかったら使ってみてください。僕も使いながら改良していきます