とある企画を細々と進めていて、その中で「あるデータを定期的にCronで取ってKVSに突っ込む」みたいなスクリプトを作ることになっていました。
で、パパッとPHPで書こうかと思っていたのですが、丁度Go言語の入門本を入手したところだったので、せっかくなのでGoで書いてみる事に。
その過程でいろいろ発見とか躓きがあったので、そのメモです。その1ってなってるけど、続くかどうかは不明。
やりたいこと
今のところ
それぞれはまだ連結してなくて、それぞれ実現したい事を単独で試している感じ。
エラー処理は何も考えてなくて、ブランク識別子( _ )で見なかったことにしている。
GETによるアクセス
これは簡単でした。
APIはOAuthとかではなくヘッダにトークンを入れて認証する形式なので、Header.Set
でセットする感じになりました。
package main import ( "fmt" "net/http" "io/ioutil" ) func main() { var req, _ = http.NewRequest("GET", "エンドポイント", nil) req.Header.Set("X-Token", "トークン") var client = new(http.Client) var resp, _ = client.Do(req) defer resp.Body.Close() var byteArray, _ = ioutil.ReadAll(resp.Body) fmt.Println(string(byteArray)) }
一見難しそうだけど、実際に書いてみるとスラスラと書けるので非常に良い。
redisにSET/GETする
さすがに標準対応していないので、redigoを使用。レリゴー。
redisはVagrantにで構築した仮想環境内にあるので、別途アドレスを指定。
package main import ( "github.com/garyburd/redigo/redis" "fmt" ) func main() { var conn, _ = redis.Dial("tcp", "192.168.33.100:6379") defer conn.Close() conn.Do("SET", "123", "aaatest") var str, _ = redis.String(conn.Do("GET", "123")) fmt.Printf("%#v\n", str) }
ライブラリのおかげが、これも書きやすかった。
JSONのパース
一番困ったのがここ。
そもそもGoにおけるJSONの扱いは、わざわざJSONに対応した構造体を宣言しないといけないので面倒そうだなという感じでした。
考えることは皆同じのようで、いろいろ調べてみるとgo-simplejsonといういい感じのパッケージがありました。
基本的にはこれで良さそうなのですが、今回取得するのは次のような・・
[ { "message_id": 1, "account": { "account_id": 123, "name": "Bob" }, "body": "Hi there!" }, { "message_id": 2, "account": { "account_id": 334, "name": "Mike" }, "body": "Hello!" } ]
最初からキーなしの配列になっているJSONで、どうやらgo-simplejsonはこの形式が上手く取れないようでした。 (もしかしたら取れるのかもしれない)
なので、大人しくencoding/json
のjson.Unmarshal()
を使うことにしました。
Unmarshalもそのままだと上のようなJSONに対応してないので、ここを参考にパースしました。
package main import ( "encoding/json" "fmt" ) const data = ` [ { "message_id": 1, "account": { "account_id": 123, "name": "Bob" }, "body": "Hi there!" }, { "message_id": 2, "account": { "account_id": 334, "name": "Mike" }, "body": "Hello!" } ] ` type accountData struct { AccountID int64 `json:"account_id"` Name string `json:"name"` } type messageData struct { MessageId int64 `json:"message_id"` Accont accountData `json:"account"` Body string `json:"body"` } type JsonData struct { Message []messageData } func main() { messageKey := make([]messageData, 0) json.Unmarshal([]byte(data), &messageKey) for _, value := range messageKey { fmt.Println(value.MessageId) } }
JSON渡すだけでいい感じにしてくれるとシンプルになって有り難いのですが、まぁあまり深く考えないようにします。
郷に入っては郷に従えとはよく言ったものです。
これから
とりあえずは各処理をつなげて想定したものを形にするのが第一目標ということで。
最終的にはcronに頼らず、タイマー処理とかも内部で完結させられればという感じです。