YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

恵贈御礼 「Go言語にWebアプリケーション開発」読了

はじめに

こんにちは、Go界のパルメザンチーズです。オライリー・ジャパンより次の本をいただきました。ありがとうございます。

Go言語によるWebアプリケーション開発

Go言語によるWebアプリケーション開発

感想

Go言語そのものをまったく書いたことがない人がいきなり本書を読むのはいささか厳しいと思いますので、あらかじめ A Tour of Go などを終え、FizzBuzz程度でもいいので簡単なコマンドラインアプリを手元で書いてみてから読み始めるのが良いと思いました。

この本で一番読み応えがあったのは、監訳者の鵜飼さんによる日本語訳版オリジナルの書き下ろしである「付録B:Goらしいコードの書き方」でした。本書を読むにあたって、まず最初に読むべき章だと言っても過言ではありません。本文に出てきたソースコードをより洗練するためにどのような点に注意すればよいかが書かれている貴重な日本語資料です。また本文のいたるところで補足するべき箇所にきめ細かな監訳注があるのも、日本語訳版の素晴らしいところです。この監訳注によって本書の品質が大幅に向上していることは間違いありません。

内容そのものは、構造化された解説書というよりも、実践的なチュートリアル本というのが適切でしょう。Goの文法はわかったけれどどこから手をつけていいかわからないという方は、まずは自分が取り組んでみたいと思っているテーマに近い章を開き、本文にしたがって少しずつコードを書きながらGoでプログラムを書くことに慣れるというのがおすすめです。サードパーティーライブラリの紹介なども多かったので、他言語の経験があるけれどもGoは初めて、という方にも肩慣らし的に試すのには手っ取り早い本だと思います。

1-3章がWebSocketを使った簡単なチャットシステムのフロントエンドとバックエンド、4章で簡単なコマンドラインツール、5-6章では並列処理を使ったデータ解析サービスとそのREST API化、7章ではファイルバックアップシステムと、テーマは多岐にわかっていますので、つまみ食いでも始めやすいです。

Goはシステムプログラミング言語としてよく知られていますが、実際にどういう形で実現できるのか、本書で実感いただけるのではないかと思います。

読書メモ

ページ数は書籍版のものです。

p.21 監訳注2

デフォルトのパッケージ名は package キーワードで指定されたものであり、ディレクトリ名ではないが、通常は揃えるという話。違ってくる場合としてよくあるのはパッケージをバージョンニングするとき。たとえば、Google Drive APIのクライアントライブラリはv1, v2, v3と3つのバージョンがある。これをimportするときは次のようになる。

import github.com/google/google-api-go-client/tree/master/drive/v3

p.81 監訳注1

パッケージ名に commonlibutil を使わないようにしようという話はgoblogに詳しく解説されている。

p.158 ノート

GorillzはGorillaのtypoだと思う。muxerも自分で書いてみるような問題もあれば良いのにと思った。

p.221 監訳注2

const では指定しないかぎり型がないという話はgoblogに詳しく解説されている。

「高熱隧道」読了

はじめに

こんにちは。Go界の日本電力です。年末に買った本を年末年始で読めなかったので、昨晩一気に読み終えました。

高熱隧道 (新潮文庫)

高熱隧道 (新潮文庫)

仙人谷ダムと黒部ダム

プロジェクトXで取り上げられてたのは、黒部ダム(通称「黒四ダム」、黒部第四発電所のためのダム)で、この高熱隧道の舞台になっている場所よりもさらに奥地に建設されています。黒部ダムの建設に関する逸話は小説をはじめ、映画、ドラマやドキュメンタリーの形で取り上げられているため、名前を知っている人も多いし、自分もプロジェクトXではじめてその壮絶な工事を知ったときには圧倒されたことを覚えています。工事での殉職者が171人にも及んだというのは、高校生の自分には衝撃的な内容でした。黒部ダムの難工事に関する物語としては「黒部の太陽」が有名でしょう。

黒部の太陽

黒部の太陽

しかし、その20年以上も前、まだ戦時中に同じ黒部川水系で、黒部ダムに負けずとも劣らない難工事が行われていたことをこの小説で初めて知りました。その内容が本当に壮絶で、真の意味でデスマーチと呼びたくなるものでした。

本当のデスマーチ

どういう意味でデスマーチだったのか、ある程度ネタバレにはなりますが書いてしまうと

  • そもそも工区にたどり着くまでの道が切り立った岩場を繰り抜いた程度のもので道幅がわずか60cm程度。資材の運搬を行うボッカが工事着工前にあっという間に5名転落死する。
  • 工区そのものが温泉湧出地帯のまっただ中を通過することが工事着工前の地質学者による調査では明らかになっていなかった。
  • 掘削する岩肌が開始30m地点ですでに摂氏65度を超え、掘り進めるにしたがってどんどん加熱、最高地点では摂氏166度に。
  • 掘削中の隧道内はサウナ状態であり人夫が切端で作業を行える時間がたった20分に。それですら、失神する人夫も数多くいた。
  • 人夫を冷やすために渓谷から汲み上げた水を人夫にかけるが、その水が隧道内にたまり人夫の膝まで、ひどい時には腹までたまるほどに。しかも岩肌に暖められて水温が摂氏45度まであがることも。
  • 岩肌がダイナマイトの発火温度を超えるほどになってしまい、設置と同時に爆発。担当していた人夫が死亡。

まだまだこれは序の口で、最終的にこの工事による殉職者が300人に迫るほどになるわけですが、それに至る過程が緻密な描写で淡々と語られていくのがこの小説の恐ろしいところです。多数の犠牲者を出しながらも工事が中止とならなかった背景には、工事の発注元の日本電力の社運をかけた工事だったことと、当時電力が国家的に求められていたこと、しかも天皇からも恩赦がでるほどであったため辞めるに辞められなかったという状況があるようでした。

吉村昭氏の綿密な調査により、工事中の隧道の様子が細かな部分まで伝わってくる、素晴らしい「記録小説」でした。小説に登場する人物や企業はフィクションではあるものの、実際にそれに対応する人物や企業がいるようです。実際に小説中の各事件での殉職者数は現実の事件と一致しています。

デスマーチ」という言葉を職業柄よく聞きますが、真の意味で「デスマーチ」の物語でした。

YAMAGUCHI::weblogの2015年を振り返る

はじめに

こんにちは、Go界の北陸新幹線です。今日でまた1歳を歳を取りました。例のやつ貼っておきます。

関連エントリ

振り返り9年目です。

ymotongpooの2015年

昨年立てた目標

まず昨年立てた2015年の目標を振り返ります。

  • Go関連情報の継続的なアウトプット
  • Android開発の技術力の向上
  • 「通知」に関する研究
  • 英語力の向上
  • 仏教について学ぶ
  • 経済について学ぶ
  • RAWデータの現像技術の向上

Go関連情報の継続的なアウトプット

今年は特にGo関連のイベントも数多く開催され、アドベントカレンダーではGoのものが3つも満員になるなど、ますますGoが普及してきたことを強く感じています。

2年前からは考えられないほどの広がりを見せていて、自分がなにかするまでもなく多くの情報が共有されています。なので去年の暮れに立てた目標は、すでにコミュニティによってなされていたなあという印象です。

Go Conferenceも去年までは自分が主催でしたが、いまはもう完全に @tenntenn に引き継ぎ、自分も一参加者として楽しませてもらっています。

今度はまた新しく、よりディープな集まりを企画したいなあと考えています。

Android開発の技術力の向上

これはこの1年でぼちぼちかけるようになった感があって、楽しくなってきたなーと思います。(外に出せないやーつが多い)

来年はAndroid Wearの開発あたりをちょっと盛り上げていきたいなあと思います。

「通知」に関する研究

これは広いテーマなので1年でぱっと何か見つかるというものでもないと思いますが、自分のなかで「コンテキスト」と「コンテンツまでの距離」というキーワードで通知に関する考察が進んだ一年でした。

そのテーマについては、対外的なイベントで話したりもして、少しずつですが整理ができてきた感じがします。

「通知」は過去2年間関わってきていますが、これからはより「通知」のデザインや体験というものが重要になってくると感じているので、2016年はより多くの方から意見を聞きながら考えを深めていきたいと思います。

英語力の向上

漠然と目標として書いていたけれども、担当するプロダクトが増えたりして、本社とのやり取りも増えたので、英語でのやり取りが増え、結果として去年よりも確実にコミュニケーションが楽になっていると感じました。ただそれはあくまで日常的な業務をこなすレベルであって、逆にだいぶ本を読んだりするのがしんどくなってるんで、来年はもうちょい英語のブログなり記事を読む機会を増やしていこうと思います。

仏教・経済について学ぶ

ここに時間が割けなかったなーというのが今年の反省点。特に経済に関しては、2016年は家計の整理や運用などをしながら、理解を深めていこうと思います。

RAWデータの現像技術の向上

今年はイタリアに旅行に行ったり台湾に旅行に行ったりと写真を撮る機会が多い1年でした。それにともなってLightroomを使う機会も増え、だいぶ使い勝手がわかってきた感じがします。

ただクロッピングはまだ苦手なんで、より素材を活かせるよう、2016年も写真撮りまくっていこうかと思います。

今年特によくやってたこと

仕事など

あまり外に書くことがないので、改めてここに書こうと思います。自分はGoogleでDeveloper Relationsという組織の中で、Developer Partnersというチームに所属していて、ざっくり言うと、大きめの企業がGoogleの技術を利用してアプリの機能向上をする支援をしたり、そういった機能の普及を行うということをしています。関わった程度の大小はありますが、今年は外に出たもので言うと、次のような事例の裏で関わっていました。

直接、表に出る機会が減っていますが、多くの優秀な開発者と関わることができて楽しい1年でした。テーマとしている「コンテンツまでの距離」と「コンテキスト」を軸として、これからも多くの企業に機能を採用してもらえるよう、お手伝いできればと思います。

ffmpeg

今年は特に動画のトランスコーディングにはまった一年でした。毎日トランスコードをしまくっているわけですが、そのなかで徐々にffmpegのオプションを変えながら、いかに良い画質で小さいファイルサイズにするか、というところを突き詰めていくのが楽しくて仕方ありません。2015年中は、以前使っていたマシンを使いまわしていたわけですが、静音化を図るために、2016年は新しいマシンを組もうかと考えています。

またVP9やH.265など新しいコーデックもそろそろ普及に関しての動きが見えてきそうなので、興味がある人を探して情報交換をする機会を作れたらなあと思います。

360度動画に関する調査

今年のGoogle I/Oでは Google JUMPProject Spotlight などの360度動画に関連する発表がありましたが、ここは今後の静止画・動画の発展の方向として確実に広がる分野なので興味を持って仕様や各社の製品などを見ていました。

特にInterBEEや各企業の展示会などで360度動画カメラなどが多く出展されていたことからも、2016年は360度動画撮影の年になるんじゃないかなと感じています。

来年に向けて

  • 動画関連技術で遊ぶ
    • 特に自宅の動画トランスコーダの新設をしていろいろとコーデックを試したい
  • アクションカムと360度カメラで遊ぶ
    • GoPro HERO4とTHETA Sを手に入れたので動画撮りまくろう
  • Androidで遊ぶ
    • 遊ぼう
  • 資産運用を真面目に考える
    • もっとよく資産をうまく運用しないと

QNAPのTurboNASが吹っ飛んでtestdiskに助けられた話

はじめに

こんにちは。この記事は pyspa Advent Calendar 2015 の22日目の記事です。Go Advent Calendarとまったく同じ日に登録したことにあとで気づいて、すごく後悔しています。そんなわけで、今日は自宅のTurboNASが吹っ飛んでtestdiskに助けられた話をします。最後提灯記事っぽいけど、1ユーザとして便利なので書きました。

TL;DR

  • TurboNASは便利だけどデータが吹っ飛ぶ危険はある
  • testdisk超助かる
  • Google Apps for unlimited storage and vaultで安心を買った

QNAPのNASは素晴らしいです

2012年2月に買ってから自宅のNASとして活躍していたQNAPのTurboNAS(TS-659+ Pro、いまは売ってないっぽい)なんですが、こいつがなかなかすぐれもので、RAID 0/1/5/6/10なんかを簡単に組めて(ソフトウェアRAID)、イーサネットポートも2口、iSCSIでも使えて、CIFS/AFP/NFSでもマウント可能、他にもメディアトランスコーダーや、DLNAサーバー等々、各種サービスもWebのGUIでちょいちょいっと簡単に設定できる。Mac使ってる人にはTimeMachineにもなってくれる便利なやつです。

f:id:ymotongpoo:20151222171138p:plain

で、写真などのメディアや必要書類をスキャンした電子ファイルの保存など、結構重要な役割を果たしていました。そんな中、今年の10月末にHDDの警告が出ていたので、新規HDDに換装しようとしたところ、久しぶりだったため手順を誤ってしまいました。

ホットスワップができるというのが製品の売りなので、とりあえず前のHDDにもどして、再構成が終わるのを待ってたんですが、なんかいやな予感がするわけです。で、再構成が終わっても、RAID5の仮想ディスク領域をマウントできない。個々のディスクは認識してるので、まさかと思って確認してみるとRAID5のパーティションテーブルがぶっ壊れてました。

すでにその時ディスクには6TB-7TBくらいのデータがあったのでかなり冷や汗モノでした。

復旧作業

最初mdadmでRAIDから外れてるディスクを追加しようとしたものの、そいつ自体のパーティションテーブルが壊れてるということで弾かれ、しょうがないのでmke2fsでスーパーブロックのアドレス見てから、e2fsckで修復試みてみたものの全然状況が変わらないんで、これ以上手をいれるのはまずいということで、RAID自体の復旧は断念しました。

しかしディスク自体はまだ生きてるようなので、上書きされてしまう前にデータのサルベージを行うことにしました。諸々探してみた中で最も信頼性が高かったのが testdisk でした。

www.cgsecurity.org

testdiskはパーティションの復旧などをTUIでサポートするというのが主な機能ですが、復旧可能パーティションに対して、拡張機能(Advanced)の中にある List メニューを選択すると、読み取れるファイルがすべて表示されます。幸い中を確認したかぎりではファイル自体は生きてそうなので、急いで3TBの外付けHDDを購入し、TurboNASに接続、testdiskで2週間かけてほぼすべてのファイルをサルベージし、事なきを得ました。

Google Apps with unlimited storage and Vault

ところで、Google Appsには「Google Apps with unlimited storage and Vault」というプランがあります。これは5名以上いれば、月々1200円で容量無制限のGoogle Driveが利用できるというものです。(もちろん他のGoogle Appsの機能も使えます)

apps.google.com

閲覧用の写真のJPEGデータはいまはGoogle Photosで管理しているので、容量を心配することないんですが、オリジナルサイズやRAWデータはやはりデータが大きく、かと言って今回のようなことがあるとせっかくの思い出が全部消えてしまうのでなかなか扱いに困ってしまいます。これまではNASですべて管理してたのですが、今回の事故を期に有志を募ってこちらのプランを契約しました。先ほどの3TBの外付けHDDが14000円弱だったので、こちらのプランのほぼ1年分の価格です。その価格で安心を買えると思ったら安いものだなと思います。

また副次的に、ウェブでもスマホでもいろいろなクライアントがあるので、どこでも中身を簡単に確認できたりするのがとても楽です。スキャンしたPDFなんかを外で楽に閲覧できるのが地味に助かっています。

おわりに

やっぱりでかいファイルが多くなるとふっとんだ時のリスクがでかいので、大人しくストレージサービス借りたほうが結果的に安いですね。

Goで良い感じに日時をパースするライブラリdatemakiの話とGo 1.6

はじめに

こんにちは、Go界の京成舎人ライナーです。このエントリは Go Advent Calendar 2015 の22日目の記事です。

今回のアドベントカレンダーに向けて、タイトルとは別のことをいろいろとやってみてたんですが、OS X 10.11 (El Capitan) でのみ発生する謎事象の原因をいろいろ調べてたらどうもGoと全然関係ないことのようで、まったくGo Advent Calendarに関係ない記事になりそうなのでやめました。

というわけで、今回はGoでの日時のパースについてです。

Goにおける日付のパース処理

いうまでもないおさらいなのですが、念の為に。Goでは日付の処理は timeパッケージ で行っています。他のプログラミング言語とは異なるフォーマットなので、初めて使うときは少々戸惑いますが、慣れてくると「2006年1月2日3時4分5秒」という決まった時刻のどの数字がどこに来るかを書くだけなので案外覚えやすいものです。

http://play.golang.org/p/wq8jrZKLjq

package main

import (
    "fmt"
    "time"
)

func main() {
    s := "2015/12/22 10:00:30"
    layout := "2006/01/02 15:04:05"
    t, err := time.Parse(layout, s)
    if err != nil {
        panic(err)
    }

    layout2 := "06年01月02日 15時04分05秒"
    fmt.Println(t.Format(layout2))
}

実行するとこのようになります。

15年12月22日 10時00分30秒

相対時間と絶対時間

timeパッケージのパース関数やフォーマット関数は上記のような数字だけの絶対時間を扱うのはとても楽なのですが、文字が入った日時などを扱おうとすると面倒です。たとえば "2015 December 21st" とかです。

また相対時間を扱うときも結構面倒だったりします。たとえば "yesterday" とか "3 days ago" とかそういうやつです。

いろいろなパターンについて @shibukawa がgistにまとめてくれています。

これを眺めるだけでも「うぁあああああ」という気持ちになるのですが、「うぁあああああ」とばかりも言ってられないので、とりあえずなんとか力技でもいいから扱えるようにしとくかー、と思ってライブラリを数カ月前に作ったのを忘れてたんですが、今日切羽詰まって思い出しました。

datemaki

なんとなく「dateが入った名前がいいなあ」と思って、伊達巻にしました。いまの季節にぴったりですね!

github.com

datemakiを使うと、日時をパースするのがどう楽になるのか、サンプルコードでご覧ください。

package main

import (
    "fmt"

    "github.com/ymotongpoo/datemaki"
)

func main() {
    exps := []string{
        "3 days ago",
        "2015 Dec 22nd 23:00:00",
        "yesterday 14:00",
    }

    for _, e := range exps {
        t, err := datemaki.Parse(e)
        if err != nil {
            fmt.Println(err)
            continue
        }
        fmt.Println(t)
    }
}

これを実行するとこのような結果になります。

# 実行時の日時は 2015/12/21 23:16:49
% go run main.go
2015-12-18 23:16:49.782843129 +0900 JST
2015-12-22 23:00:00 +0900 JST
2015-12-20 14:00:00 +0900 JST

Parse() という雑な関数に投げただけでちゃんと返してくれました!

datemakiの今後

最初の実装はかたっぱしから正規表現かけたり、序数のサフィックスを持ってるかを適当に判定したりして、漏れがかなりありそうです。テストケースも結構雑なので多分バグります。またいまは実行時間からの相対時間などしかとれないですが、ログを解析するなどの場合はログの取得時からの相対時間もとれないといけないので、ちゃんと状態管理用の構造体を持たせないといけないなあと実装しながら思いました。

Pull Requestなどは随時募集してますが、気が向いた時にしか反応しないと思います。ごめんなさい。(先に謝っていくスタイル)

Go 1.6でのtimeパッケージの変更

ところで、みなさんGo 1.6 beta1はすでにチェケラしてますかぁ~!?Go 1.6のリリースノートをチラ見すると超下の方にちっさくtimeパッケージについての変更予定が書いてあります。(まだリリースしてないので変更しないかもしれない可能性もある。たぶんそんなことないけど。)

  • Go 1.6 Release Notes DRAFT - The Go Programming Language

    The time package's Parse function has always rejected any day of month larger than 31, such as January 32. In Go 1.6, Parse now also rejects February 29 in non-leap years, February 30, February 31, April 31, June 31, September 31, and November 31.

書いてあるままを読むと「Go 1.6ではこれまでエラーにしてなかったうるう年でない2月29日等々もエラーにしますよ」って書いてあります。試しに次のコードをGo 1.5.2とGo 1.6 beta1で実行してみます。

package main

import (
    "fmt"
    "runtime"
    "time"
)

func main() {
    fmt.Println("Go version", runtime.Version())
    s1 := "2015/04/31 10:00:00"
    s2 := "2015/04/31 25:00:00"

    layout := "2006/01/02 15:04:05"

    t1, err := time.Parse(layout, s1)
    if err != nil {
        fmt.Println("[s1]", err)
    }
    fmt.Println("[s1]", s1, "->", t1)

    t2, err := time.Parse(layout, s2)
    if err != nil {
        fmt.Println("[s2]", err)
    }
    fmt.Println("[s2]", s2, "->", t2)
}
  • Go 1.5.2
% PATH=/opt/go/go1.5.2/bin:$PATH GOROOT=/opt/go/go1.5.2 go run main.go
Go version go1.5.2
[s1] 2015/04/31 10:00:00 -> 2015-05-01 10:00:00 +0000 UTC
[s2] parsing time "2015/04/31 25:00:00": hour out of range
[s2] 2015/04/31 25:00:00 -> 0001-01-01 00:00:00 +0000 UTC
  • Go 1.6 beta1
PATH=/opt/go/go1.6.b1/bin:$PATH GOROOT=/opt/go/go1.6.b1 go run main.go
Go version go1.6beta1
[s1] parsing time "2015/04/31 10:00:00": day of month out of range
[s1] 2015/04/31 10:00:00 -> 0001-01-01 00:00:00 +0000 UTC
[s2] parsing time "2015/04/31 25:00:00": hour out of range
[s2] 2015/04/31 25:00:00 -> 0001-01-01 00:00:00 +0000 UTC

そのようになってます。しかし、俺が一番ほしいのは時刻の部分の繰上げです。たとえばテレビ欄とかに出てくる「25:30」みたいなのをパースする機能なので逆方向に行っちゃってますね。

というわけでこの辺ちょっと本家にパッチ送るモチベーション湧いてきました。とりあえずdatemakiを良い感じにしつつ、ぼちぼちやってきます。みなさん、お正月に伊達巻見たらdatemaki思い出してください。

明日のラインナップは次の皆さんです!!

(訂正)2016.01.05 完全に1.6のリリースノートを逆に読み違えてました。1.6では日付のチェックがより厳しくなりました、というのが正です。