2014年1月9日木曜日

Golang Cafe #11を開催しました。

Golang Cafe #11を開催しました。

今回扱ったのはarchiveパッケージでarchive/tararchive/zipが含まれています。
サンプルコードはgithubにありますのでごらんください。

archiveパッケージの話題に入る前に、「プログラミング言語Goフレーズブック」での質問で、Type Assertionの例で書籍のサンプルを動かすとコンパイルエラーになる。interfaceの型に変えるとコンパイルが通る。という内容のものがありました。
該当のコードは以下のものになります。(以下のコードは修正済みです)
Example構造体がPublicインターフェイスを実装しているかどうかをチェックするために、e.(Public)という書き方をして、Type Assertionを使って確認するべきという趣旨の事が書かれていますが、なぜかコンパイルエラーということで悩みました。一見、正しいようにみえるのですが、Type Assertionの仕様を確認すると、インターフェイスの変数に対して行うもので、そもそも構造体変数に対して行うものではなかった。という結論に至りました。ぱっと見だとすぐに発見できないので、慣れておいた方がいいです。

package typeassertion

type Public interface {
        Name() string
}

type Example struct {
        name string
}

func (e Example) Nme() string {
//func (e Example) Name() string {
        return e.name
}

// func NewExample() Example {
//         return Example{"No Name"}
// }

func NewExample() Public {
        return Example{"No Name"}
}

func NewExample2() Public {
        var p Public
        e := Example{"No Name"}
        p.(Example)
//        e.(Public)

        return e
}

次に、本題のarchiveパッケージのサンプルを見ていきました。
まずは、tarのサンプルから。
ポイントは、tarに書き込むための、Writerを生成するために、tar.NewWriter()を呼び出します。引数はio.Writerなので、os.Create()などで、生成したFileを引数にすれば、ファイルに書き込む事ができます。
tar.NewWriter()で受け取ったWriterは必ずClose()してください。MacOSXだと、標準のアーカイブユーティリティで展開できない(エラーが発生する)という現象が出ました。
(ただ、Win版だと発生せず、OSに依らず、Goのプログラムから読み出すと読み出せたりするのですが…)

Writerを生成したら、あとは、Headerを書き、Bodyを書く。という事を繰り返せば、tarが完成します。

反対に、tarを読み出す時は、tar.NewReader()を呼び出し、Readerを生成します。
reader.Next()を呼び出すと、Headerが取れます。その後、readerからbodyを読み出せばファイルが取得できます。説明が雑なのでサンプルコードと一緒にごらんください。

次に、zipのサンプルですが、tarのサンプルを見た後なら、大体同じような構成なので、難しくないと思います。

zipを読み出す時もtarを読み出す時と変わらないので、特に難しくないでしょう。

結果、tarは圧縮するものではないので、容量が変わらないのは良いとして、zipは多少圧縮されるのかな?と思ったらそんなに変化が無く、画像を扱ったからかな?と思いましたが、テキストにすれば変化が出るのでしょうか…。

で、ディレクトリを走査して、大量のテキストをzipに入れようと試みましたが、時間がなく、stackoverflowのサンプルを発見した所で終わりました。ポイントは、path/filepath#Walk()を使って、再帰的に探していくという事になります。
これは、今後の課題になると思います。

次回は、compressパッケージをいじる会になります。