はじめてのGo

今さらながら、Goをもう少し読み書きできるようになりたいな、と思い。

A Tour of Go を一通り読んで、

などを参考にしつつ、写経というかんじで Twitterのtimelineを取得するものをまずは書いてみた。

package main

import (
	"encoding/json"
	"fmt"
	"github.com/garyburd/go-oauth/oauth"
	"github.com/typester/go-pit"
	"log"
	"net/http"
	"os/exec"
	"runtime"
)

func main() {
	profile, err := pit.Get("twitter.com", pit.Requires{
		"consumer_key":    "<consumer key>",
		"consumer_secret": "<consumer secret>",
	})
	if err != nil {
		log.Fatal(err)
	}

	client := oauth.Client{
		TemporaryCredentialRequestURI: "https://api.twitter.com/oauth/request_token",
		ResourceOwnerAuthorizationURI: "https://api.twitter.com/oauth/authorize",
		TokenRequestURI:               "https://api.twitter.com/oauth/access_token",
	}
	client.Credentials = oauth.Credentials{(*profile)["consumer_key"], (*profile)["consumer_secret"]}

	accessToken, existsAccessToken := (*profile)["access_token"]
	accessTokenSecret, existsAccessTokenSecret := (*profile)["access_token_secret"]
	// get access token
	if !(existsAccessToken && existsAccessTokenSecret) {
		// open authorization url
		tempCred, err := client.RequestTemporaryCredentials(http.DefaultClient, "oob", nil)
		if err != nil {
			log.Fatal(err)
		}
		url := client.AuthorizationURL(tempCred, nil)

		if runtime.GOOS == "darwin" {
			err := exec.Command("open", url).Run()
			if err != nil {
				log.Fatal(err)
			}
		} else {
			fmt.Printf("open %s\n", url)
		}
		print("PIN: ")

		// get credentials by PIN code
		var code string
		if _, err := fmt.Scanln(&code); err != nil {
			log.Fatal(err)
		}
		credentials, _, err := client.RequestToken(http.DefaultClient, tempCred, code)
		if err != nil {
			log.Fatal(err)
		}

		// set to Pit
		accessToken = (*credentials).Token
		accessTokenSecret = (*credentials).Secret
		pit.Set("twitter.com", pit.Profile{
			"consumer_key":        (*profile)["consumer_key"],
			"consumer_secret":     (*profile)["consumer_secret"],
			"access_token":        accessToken,
			"access_token_secret": accessTokenSecret,
		})
	}

	credentials := &oauth.Credentials{
		Token:  accessToken,
		Secret: accessTokenSecret,
	}
	resp, err := client.Get(http.DefaultClient, credentials, "https://api.twitter.com/1.1/statuses/home_timeline.json", nil)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	var tweets []struct {
		Text string
		User struct {
			ScreenName string `json:"screen_name"`
		}
	}
	if err := json.NewDecoder(resp.Body).Decode(&tweets); err != nil {
		log.Fatal(err)
	}

	for _, tweet := range tweets {
		fmt.Printf("@%s: %s\n", tweet.User.ScreenName, tweet.Text)
	}
}

Emacs設定

などを参考に、
go-modeは勿論導入、ファイル保存時に自動でgofmtかけるようにし、
helm-go-packageでhelmインターフェース使って選択しドキュメント参照、
gocode入れてgo-autocompleteでイイカンジの補完、
go-eldocでも定義参照できるように、
など。これだけ揃っていると便利。
型があるとここまで補完が効くのかー、という驚きを感じてしまったPerl脳。
文法まだ慣れないけど書いているうちに少しずつコツつかめるようになるかな…?もうちょい色々チャレンジしてみよう。