2014/12/15


この記事は Go Advent Calendar 2014 16日の記事ではありません
docomo Developer support | NTTドコモ

Docomo が公開する API など開発者向けの情報を提供します。アプリケーションの開発にご活用ください

https://dev.smt.docomo.ne.jp/
DocomoruでBOTと雑に会話する - Qiita

docomoが提供している雑談対話APIを利用し...

http://qiita.com/r7kamura/items/55f398624dbce1c6dc14

DoCoMo が雑談対話APIというのを出していたのでサクッっとlingr botを書いてみた。

mattn/go-docomo - GitHub
https://github.com/mattn/go-docomo

lingr の vim 部屋上に vimgirl という名前の bot として動いています。

Vimgirl lingrbot

Vimgirl lingrbot これは これは、NTT DoCoMo が提供する雑談対話 API を利用して実装されたチャットサービス lingr の bot です。

http://mattn.tonic-water.com/vimgirl/

キャラクタは orgachem さんが描いている絵を使わせて頂きました。(CC BY)

vimgirl: こんにちわ
この様に vimgirl: のプレフィックスを付けて会話すると
vimgirl

適当な会話をしてくれます。ご活用下さい。


2014/12/08


GoLangでJavaのenumっぽいライブラリ作った話 - おいぬま日報

なんとかなるわけなんだけど、これを毎回書くのは面倒なので...

もっと良いやり方があったらぜひ教えて欲しいところです。

http://oinume.hatenablog.com/entry/introducing-goenum

golang でユーザ型の値を文字列化する場合 Stringer というインタフェースを実装します。具体的には

func (l Lang) String() string {
    switch l {
    case Go:
        return "Go"
    case Python:
        return "Python"
    case Ruby:
        return "Ruby"
    }
    panic("Unknown value")
}

上記サイトで書かれている様に String() という関数を実装します。実は golang のオフィシャルから stringer という、その名の通りのツールが提供されています。

まず、Stringer を実装していないコードを書きます。

package main

import (
    "fmt"
)

type Fruit int

const (
    Apple Fruit = iota
    Orange
    Banana
)

func main() {
    var fruit Fruit = Apple
    fmt.Println(fruit)
}

このまま実行すると 0 と表示されます。ここで以下の様にして stringer というツールをインストールします。

$ go get golang.org/x/tools/cmd/stringer

そしてソースコードと同じディレクトリで以下の様に実行します。

$ stringer -type Fruit fruit.go

すると fruit_string.go というファイル名の以下のコードが生成されます。

// generated by stringer -type Fruit fruit.go; DO NOT EDIT

package main

import "fmt"

const _Fruit_name = "AppleOrangeBanana"

var _Fruit_index = [...]uint8{51117}

func (i Fruit) String() string {
    if i < 0 || i >= Fruit(len(_Fruit_index)) {
        return fmt.Sprintf("Fruit(%d)", i)
    }
    hi := _Fruit_index[i]
    lo := uint8(0)
    if i > 0 {
        lo = _Fruit_index[i-1]
    }
    return _Fruit_name[lo:hi]
}

あとはこのソースも含めてビルドし、再度実行してみると今度は Apple と表示される様になります。便利ですね。

尚、const で iota を使う場合ですが、上記の様に型を指定しておくと違う型の変数へ Apple を代入する際にエラーが出て便利です。

package main

import (
    "fmt"
)

type Fruit int
type Animal int

const (
    Apple Fruit = iota
    Orange
    Banana
)

const (
    Monkey Animal = iota
    Elephant
    Pig
)

func main() {
    var fruit Fruit = Apple
    fmt.Println(fruit)

    fruit = Elephant
    fmt.Println(fruit)
}
./fruit.go:26: cannot use Elephant (type Animal) as type Fruit in assignment

2014/12/02


通常、golang のデフォルトの HTTP クライアントは環境変数 HTTP_PROXY もしくは HTTPS_PROXY を参照してプロキシに接続し、環境変数 NO_PROXY で指定されたホストが無視される仕組みになっています。しかし一般ユーザにとって環境変数の設定は、難易度の高い作業だったりします。

使用例

たとえばこういうコードに…

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    res, err := http.Get("http://www.google.com")
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
    defer res.Body.Close()
    io.Copy(os.Stdout, res.Body)
}

一行追加すると:

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"

    _ "github.com/mattn/go-ieproxy/global" // ← この行
)

func main() {
    os.Setenv("HTTP_PROXY""")
    os.Setenv("HTTPS_PROXY""")
    res, err := http.Get("http://www.google.com")
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
    defer res.Body.Close()
    io.Copy(os.Stdout, res.Body)
}

たったこれだけで、IE のプロキシ設定が引き継がれます。無ければデフォルトと同じ様に、環境変数で動作します。

仕組み

ieproxy は ieproxy.ProxyFromIE という関数を提供していて、これが http.Transport.Proxy を実装しています。この関数は http クライアントのプロキシ仲介有無を行っているのでつまりは http.Client の Proxy を設定できます。http.Cilent が HTTP リクエストを実行する際にはこの Proxy が呼び出されて判定処理が行われますが、ieproxy.ProxyFromIE はレジストリから IE のプロキシ設定を取得しつつプロキシの判定を行うような実装になっているので、このように HTTP 通信に引っかけてプロキシをすげかえることができるわけです。

さらに github.com/mattn/go-ieproxy/global パッケージでは http.DefaultTransport.Proxy を ieproxy.ProxyFromIE に書き換え(!)しているので、インポートするだけですべての HTTP 通信が(標準の http パッケージを利用していれば)勝手に IE のプロキシ設定になります。

注意: IE でしかビルド出来ません。

参考資料: ソースに一行追加するだけですべての HTTP 通信をロギングするモジュールを書いた #golang - 詩と創作・思索のひろば

mattn/go-ieproxy - GitHub
https://github.com/mattn/go-ieproxy