2016/12/21


ここ最近、gops に関する記事を2つ書いた。

golang で書かれたプロセスのリソースを外部から監視/操作できる「gops」 - Qiita

この記事は [Go Advent Calendar 2016](http://qiita.com/advent-calendar/2016/go) の3日目の記事です。 # はじめに 今回は gops...

http://qiita.com/mattn/items/a92f69ff18eb5cbcdd59
稼働中のバッチを監視したくなったら Mackerel Custom Metrics が便利 - Qiita

この記事は [Mackerel Advent Calendar 2016](http://qiita.com/advent-calendar/2016/mackerel) の 12/13 日の記事です...

http://qiita.com/mattn/items/882a1924a1d706d127a2

実は gops には一つ注意点がある(あった)。プロファイル結果をファイルとして出力しているためにお掃除しているコードがあるのだけど、これを行う為に SIGINT をキャッチしてしまっている。なので既存で CTRL-C をハンドリングしていたコードがちゃんと働かなくなるという問題があった。

Allow starting the agent without installing a signal handler by cezarsa · Pull Request #19 · google/gops · GitHub

The idea of exposing this type was for forward compatibility. I wouldn't care about breaking API at ...

https://github.com/google/gops/pull/19

が、先ほど修正がマージされ

if err := agent.Listen(&agent.Options{NoShutdownCleanup: true}); err != nil {
    log.Fatal(err)
}

この様にオプションで終了時処理を無効にしつつ起動する事ができる様になった。これで安心してプロダクションコードでも使用できる様になった。


2016/12/03


冒頭でもお話させて頂いた通り、僕は YAPC に何回も誘われながらも結局参加できなかったというのが気持ちの奥にずっとあり、一度くらいは出ておくべきだったのかなと考えていたので今回、牧さんからお誘いを貰った時はお詫びをするなら今しかないと思っていました。はじめは15分とか30分程度のトークかなと思っていたら気付けば builderscon 2016 第1回目のド頭で1時間枠を割り当たっていました。

内容は「OSS は Windows で動いてこそ楽しい」というお題で Windows アプリの開発のつらさ、闇、そしてGo言語の誕生と希望について熱く語らせて頂きました。おまけで Vim の話もさせて頂きました。いやどちらかというと Vim の話がメインだったかもしれません。

OSS は Windows で動いてこそ楽しい - builderscon2016
https://mattn.github.io/builderscon2016/

こういう公の場で、しかも全裸で登壇させて頂くのは初めてだったのでとても緊張しました。ダジャレが言えたので満足でしたが、ネタ満載で技術要素が薄かったのは、果たして良かったのだろうかと自問自答中です。

昼ごはんは牧さんと Dave Cheney 氏とハンバーガーを食べました。Dave に「Go の Type Alias どう?」って聞いたら10分くらい熱く語っておられました。

Simulating minicomputers on microcontrollers | Dave Cheney

Recent Posts Simulating minicomputers on microcontrollers Go 1.8 toolchain improvements Do not fear ...

https://dave.cheney.net/2016/12/03/simulating-minicomputers-on-microcontrollers
他の方の発表も幾らか見せて頂きましたが、特に印象に残ったのは以下の3つです。
The Open Beer Server - theory and the implementation - builderscon tokyo 2016

Abstract 皆さんビールは好きですか? 私は大好きです. その好きさが昂じた所,ひょんなことからビールサーバを入手する機会に恵まれました.なるほど中身を見てみるとビールサーバの内部実装というのは...

https://builderscon.io/builderscon/tokyo/2016/session/a5c0b3c8-a3de-451f-bc6b-a6a1f54e73c1

ビールサーバを作る事の難しさ、ビール製造会社の希薄な関係、そして何よりも「ビールサーバを作るには金がいる」というありがたい知見を得られた。ビールサーバを自作する際にはぜひ参考にしたいと思います。はい、作りません。

そろそろプログラマーもFPGAを触ってみよう! - Qiita

##そろそろプログラマーもFPGAを触ってみよう! これは[builderscon tokyo 2016](https://builderscon.io/builderscon/tokyo/2016)...

http://qiita.com/kazunori279/items/a9e97a4463cab7dda8b9

FPGA は大人の電子ブロックと題して今後のクラウドサーバの動向が FPGA の登場によりがらりと変わりうると教えて頂きました。懇親会で kaoriya さんと「FPGA と Vim をどうにか組み合わせられないか」という話で盛り上がってしまい、僕らはどこでも Vim の話だなw と Vimmer の精神構造が若干おかしいと自覚しました。

builderscon tokyo 2016 で「 Bluetooth キーボードの作りかた」を喋りました | tech - 氾濫原

ありがとうございました。 聞いたトークで印象に残ったもの OSS は Windows で動いてこそ楽しい - builderscon tokyo 2016 mattn さんが思ったより全くオッサン感な...

https://lowreal.net/2016/12/03/1

使いたいキーボードが手に入らないから作っちゃったというモチベーションの高さに感動するセッションでした。結局自分で PCB Milling したって話はすごいと思った。発表前に隣に座っておられたので挨拶すれば良かった。

正直、お詫びのつもりで登壇したけど緊張で吐きそうだったし、しばらく登壇はいいかなw という気持ちですハイ。あと4時起きだったのでこれ書きながら眠くて仕方ないです。


2016/12/02


追記: 修正が中途半端だったのでいったんリバートされ go1.9 で修正される事になりました。

UNIX に慣れている人であれば問題ないのですが、Windows で zip や tar.gz, tar.bz2, tar.xz を開くのは意外と不便で専用アーカイバをダウンロードしてきてインストールする必要があり、割かし不便なのですが archiver というツールを使うと以下のフォーマットを簡単に作成、展開できるようになります。

  • .zip
  • .tar
  • .tar.gz
  • .tgz
  • .tar.bz2
  • .tbz2
  • .tar.xz
  • .txz
  • .rar (開くのみ)

インストールは golang が入っていれば簡単です。

$ go get github.com/mholt/archiver/cmd/archiver

使い方も簡単で、圧縮は以下の手順。

$ archiver make [archive name] [input files...]

※形式は拡張子で判断します。

解凍は以下の手順。

$ archiver open [archive name] [destination]

シングルバイナリで動作するので、別の Windows にポンとバイナリ一つ持っていけば同様に動作するのが良いですね。

なお go1.7 の場合、zip のタイムスタンプが正しく保存されません。

Goでファイルをzip圧縮したときにタイムスタンプがずれる問題の回避策 - Qiita

#初めに Goでファイルをzip圧縮する方法と、それに伴う問題と、その回避の記事です。 (更にいい方法がありましたら、ご指摘よろしくお願い致します) #実験環境 go version go1.4.2 ...

http://qiita.com/yuki2006/items/0211421792bd788f8153
Golangで特定のディレクトリをZIP化する処理を書いた | SHINOFARAの日常

Go playground にも書いたけど、動かない 対象となるファイルが多すぎたか package main import ( "archive/zip" "fmt" "io" "io/ioutil...

https://log.shinofara.xyz/2016/06/30/golang%E3%81%A7%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%82%92zip%E5%8C%96%E3%81%99%E3%82%8B%E5%87%A6%E7%90%86%E3%82%92%E6%9B%B8%E3%81%84%E3%81%9F/
Golangのarchive/zipを使うと、タイムゾーンが強制UTCになる問題! | SHINOFARAの日常

archive/zip/struct.go#L170 このファイルの 170 func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16...

https://log.shinofara.xyz/2016/06/30/golang%E3%81%AEarchivezip%E3%82%92%E4%BD%BF%E3%81%86%E3%81%A8%E3%80%81%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%BE%E3%83%BC%E3%83%B3%E3%81%8C%E5%BC%B7%E5%88%B6utc%E3%81%AB%E3%81%AA%E3%82%8B%E5%95%8F%E9%A1%8C/
ZIP化の時に、タイムスタンプが強制UTCになってしまう。 Issue #46 shinofara/stand GitHub

https://golang.org/src/archive/zip/struct.go#L171 の仕様上 強制的にUTC時刻としてみなされてしまっている。 その為、ロケール毎に時間を増減させないと...

https://github.com/shinofara/stand/issues/46

go1.8 でビルドすると正しく扱える様になります。go1.8 では上記の様なワークアラウンドが必要無くなります。逆に言うと、これらのワークアラウンドがあると問題が発生してしまいます。

Go 1.8 Release Notes - The Go Programming Language

DRAFT RELEASE NOTES - Introduction to Go 1.8 Go 1.8 is not yet released. These are work-in-progress ...

https://beta.golang.org/doc/go1.8#archive_zip
Gerrit Code Review

...

https://go-review.googlesource.com/#/c/18274/

こういった問題ではバージョン毎に処理を分ける必要があります。以下では go1.7 と go1.8 で動作を分けたい場合のコードを説明します。まずはワークアラウンドを行っている処理を抽出します。

func FileInfoHeader(fi os.FileInfo) (*zip.FileHeader, error) {
    size := fi.Size()
    fh := &zip.FileHeader{
        Name:               fi.Name(),
        UncompressedSize64: uint64(size),
    }

    // 現在のLocalを取得する。 
    local := time.Now().Local()

    //時刻のoffset(秒)を取得する。
    _, offset := local.Zone()

    //ファイルスタンプの時間に時差分を追加する。
    fh.SetModTime(fi.ModTime().Add(time.Duration(offset) * time.Second))
    fh.SetMode(fi.Mode())
    var uintmax = uint32((1 << 32- 1)
    if fh.UncompressedSize64 > uint64(uintmax) {
        fh.UncompressedSize = uintmax
    } else {
        fh.UncompressedSize = uint32(fh.UncompressedSize64)
    }
    return fh, nil
}

ここを別のソースファイルに切り出します。その際 build constraints に go1.7 と !go1.8 を指定します。

// +build go1.7
// +build !go1.8

package main

func FileInfoHeader(fi os.FileInfo) (*zip.FileHeader, error) {
    size := fi.Size()
    fh := &zip.FileHeader{
        Name:               fi.Name(),
        UncompressedSize64: uint64(size),
    }

    // 現在のLocalを取得する。 
    local := time.Now().Local()

    //時刻のoffset(秒)を取得する。
    _, offset := local.Zone()

    //ファイルスタンプの時間に時差分を追加する。
    fh.SetModTime(fi.ModTime().Add(time.Duration(offset) * time.Second))
    fh.SetMode(fi.Mode())
    var uintmax = uint32((1 << 32- 1)
    if fh.UncompressedSize64 > uint64(uintmax) {
        fh.UncompressedSize = uintmax
    } else {
        fh.UncompressedSize = uint32(fh.UncompressedSize64)
    }
    return fh, nil
}

これでこのファイルは go1.8 未満の場合しかビルドされなくなります。あとは go1.8 以降のバージョンでビルドされる様に go1.8 の build constraints が付いた、ワークアラウンドを実行しないファイルを用意します。

// +build go1.8

package foo

import (
    "archive/zip"
)

func FileInfoHeader(fi os.FileInfo) (*zip.FileHeader, error) {
    // ワークアラウンドしないコード
    size := fi.Size()
    fh := &zip.FileHeader{
        Name:               fi.Name(),
        UncompressedSize64: uint64(size),
    }

    fh.SetModTime(fi.ModTime())
    fh.SetMode(fi.Mode())
    var uintmax = uint32((1 << 32- 1)
    if fh.UncompressedSize64 > uint64(uintmax) {
        fh.UncompressedSize = uintmax
    } else {
        fh.UncompressedSize = uint32(fh.UncompressedSize64)
    }
    return fh, nil
}
これで、go1.7 未満であればワークアラウンドが実行されるバイナリが、go1.8 以降であればワークアラウンドを実行しないバイナリが生成されます。

build constraints については、みんなのGo言語にて説明と用法含めて書かれています。

みんなのGo言語【現場で使える実践テクニック】 みんなのGo言語【現場で使える実践テクニック】
松木雅幸, mattn, 藤原俊一郎, 中島大一, 牧 大輔, 鈴木健太
技術評論社 / ¥ 2,138 (2016-09-09)
 
発送可能時間:在庫あり。