仕事で1か月間に新しく6言語を使ったのだが、その中で最も触ったのがGo
色々と想像と違ってたので、Goを勉強始めるあたりから書いていく
使う前の印象(全然間違えてた)
天才技術者エリート集団 Googleの作った最高の言語
コンパイル言語で、C言語並みの実行速度と スクリプト言語並みの作業効率
ゴルーチン等の、高速な非同期をつかった次世代Web言語
ひゃっほ~~
目的
DevOps目的で、チャットBOTを作る
プロジェクトに使う各種ツールのURLやディレクトリを教えたり
新人が入った際のアカウント追加をサポートしたり
ソースコードのCIや ビルドを行ったり
Deployを行ったり
メトリクスのアラート出したり
・・・
色々なオペレーションをするためのサンプル
ファーストターゲット
Slackで動くBOT
AWSのECR上にUpされたコンテナのリスト表示、Tag指定でDeployする
SlackBot
Slack側の設定
Slack側の設定はほかの人のブログみてもらおう
全容
今回は github.com/nlopes/slack を利用する
ので パッケージで上記を指定する
Golangはコンパイルエラーが厳しく、使ってないものをimportするとコンパイルしてくれない
main.go
package main import ( "log" "net/http" "os" "github.com/kelseyhightower/envconfig" "github.com/nlopes/slack" ) type envConfig struct { Port string `envconfig:"PORT" default: "3000"` BotToken string `envconfig:"BOT_TOKEN" required: "true"` BotID string `envconfig:"BOT_ID" require: "true"` ChannelID string `envconfig:"CHANNEL_ID" require: "true"` } func main() { os.Exit(_main(os.Args[1:])) } func _main(args []string) int { var env envConfig if err := envconfig.Process("", &env); err != nil { return 1 } client := slack.New(env.BotToken) slackListener := &SlackListener{ client: client, botID: env.BotID, channelID: env.ChannelID, } go slackListener.ListenAndResponse() if err := http.ListenAndServe(":"+env.Port, nil); err != nil { log.Printf("[Error] %s", err) return 1 } return 0 }
slackListenerは後で
package
package名mainは特殊である。
このパッケージのみ エントリーポイントとしてmain関数が機能する
import
importはとても便利。今までGoを使ってパッケージの依存関係なので悩んだことはなかった
(ただし duplicate importは 非常にダメだ・・・ )
Githubのリポジトリから直接持ってこれるのも素晴らしい
さすがGoogleだ
コード所感
文法は慣れるしかないが、C言語やJava等のメジャーな文法とは大きく変えてきている
全体的にGoはダックタイピングだ
変数や関数名の頭を小文字にすると外部パッケージからアクセスできないので、Publicな関数や変数は大文字スタートにする
また、C言語では暗黙的型変換されるもの(int32, int64 なども)も明示的にキャストしなければエラーである
エントリポイント
mainのところはおまじないとして なんとなく意味わかるでスルーしよう
envconfig
main_ 実質のメイン
envconfigは上記Githubからのパッケージで、環境変数を構造体にマッピングしてくれる
err := envconfig.Process("", &env);
envconfig.Process にて環境変数が設定されていれば構造体に入る
:= は、変数の宣言、定義、代入である(関数内でのみ使用できる)
例えば
hoge := func() は
var hoge = func()
とだいたい同等である
ただ、使った感じ微妙にスコープが違う
nlopes/slack
client := slack.New(env.BotToken)
にて、nlopes/slackのインスタンスを作成する
もちろん env.BotTokenは、環境変数 BOT_TOKENに入っているトークンだ
構造体作成
slackListener := &SlackListener{ client: client, botID: env.BotID, channelID: env.ChannelID, }
来た。。これは構造体の作成(new)を行っている
GoではClassは無く C言語のように 構造体を作成しそこにデータを保存し、関数に構造体を渡す
つまり 全くオブジェクト指向じゃない!
そして 構造体の作成方法が何種類もある
type Hoge struct{ Name string Age int64 } // newの場合は 宣言と同時に初期化できない hoge1 := new(Hoge) hoge1.Name = "HOGE" hoge1.Age = 10 // &でも構造体を作成できる hoge2 := &Hoge hoge2.Name = "HOGE" hoge2.Age = 10 // &は定義時に初期化可能 hoge2 := &Hoge{ Name: "HOGE", Age: 10 } // 構造体のフィールド名省略可能 hoge2 := &Hoge{ "HOGE", 10 }
つまり &を使ったものだけ覚えておけば良いと今の時点では思っている
Listen
go slackListener.ListenAndResponse() err := http.ListenAndServe(":"+env.Port, nil)
go の部分が Golangの特徴である ゴルーチン
ゴルーチンは非同期で実行されるため、 slackListener.ListenAndResponse() が終了しなくても
即座に次の行へ制御がいき http.ListenAndServeが実行される
slackListenerの中身は後で勉強するとして、大雑把にいうと WebSocketを待機していて、Slcakとアクセスをする
http.ListenAndServeにて Listenを行う
この時点の感覚
Goのコードはオブジェクト指向ではなく、予想以上に低レイヤーであった
C言語を書きやすくした Better C言語である
ゴルーチンは非同期をわかりやすく解決していて使いやすそう
ただ 予想より難しい言語で、PHPerが移住する場所としては不適切ではないか?
Web言語として優れているとは現時点ではいいにくい(あくまで Better C)