技術書典7でGo言語の本を頒布します

今週末はいよいよ技術書典7ですね! 今回はGo言語の標準パッケージの解説本を頒布予定です。 web-apps.tech: サークル詳細ページ 当初の予定では全パッケージを詳解!みたいな予定だったんですが、ページ数が増えまくった結果、残念ながら26個しか詳解できませんでした。 108ページで一冊1,000円、電子版もあるよ、の予定です(電子版と両方での割引をどうしようか今考えてます)。 サークルスペースは「か11C」です。

2019-09-19 · nasa9084

Raspberry Pi zero W + IR

家で転がっていた使われないでいたRaspberry Pi zero Wを使って、家庭内のリモコン機器を自動化しようと思い立ち、秋葉原くんだりまで行って諸々部品を買ってきました。 ゴミを二つほど生成したのち、最終的に動くモノができましたので備忘録的に残しておきます。 pic.twitter.com/e55qxX5GL6 — nasa9084@某某某某(0x1a) (@nasa9084) July 29, 2019 主に「格安スマートリモコンの作り方 」を参考にしました。部品を購入した店は秋月電子で、商品ページの下の方にある「店舗情報」のリンクをクリックすると店内のどの棚に商品があるのかわかり便利です。どの部品も特に珍しい部品ではないため、商品自体がなくなっているようなことは(Pi zero用ユニバーサル基板をのぞき)まず無いように思えます。また、手持ちで0Ω抵抗が(なぜか)在庫してあったため、ジャンパ線代わりに使用しています。 一番見つけづらかったのがPi zero用ユニバーサル基板ですが、これは店の中ではなく、外のRaspberry Pi関連部品が置いてあるところにありました。 上記のQiita記事はさほど古いモノではないため、価格も変わってなかったように思えますが、動くモノができるまでにゴミを二つほど生成した都合上、三倍程度のコストがかかりました。回路周りや半田付けがあまり得意ではない人は覚悟(というほどの額ではないですが)しておいた方が(材料を余分に買っておいた方が)良いでしょう。 余談ですが部品を購入した際、近くのあきばおーでTranscendのmicro SDが安くなっていたため、大して使い道も考えずに32GBのモノを5枚ほど購入しました。 ほとんどの情報は参考にしたQiita記事にまとまっているため詳細は端折りますが、変更点として赤LEDを足してあります。ピカッと可視光が光るので、実行されたということを確認するのに便利です。 参考記事には実際の配線図だけはなかったので、紹介します。 上図が部品面、下図が半田面です。MOSFET 2N7000は平らな面が図の上側、MOSFET IRFU9024NPBFは放熱板(?)が図の下側、赤外線LEDは欠けている側(カソード?)が図の右側、赤LEDは欠けている側が図の左側、赤外線受光モジュールOSRB38C9AAは受光部が図の上側を向くように配置します。私は受光モジュールは図の下方向に向けて折り、受光部が天を向くような形にしました。 ブレッドボード上で配線してそのまま基板に移植したような形になっているため、複雑な配線もなく比較的簡単かと思います。 IRFU9024NPBFの左下はジャンパなので、半田面で配線してもかまいません(私は0Ω抵抗を使用した関係で部品面を通しています)。 実際に配線したもの。右側に温度センサを追加しています 赤外線コードの学習・実行も参考記事通りpigpioを使用しましたが、毎度SSHしてコマンドを実行するのは面倒なため、GoでAPIサーバを実装しました。Goで赤外線をGPIOでいい感じにアレするようなパッケージが見当たらなかったので、GoからPythonのスクリプトを叩くという残念なコードになっております。いいパッケージがあれば誰か教えてください。 systemdかなんかでデーモン化したりなんかして起動しておくと、例えば、 1 $ curl http://raspberrypi.local/playback?key=light:off とかすると部屋の電気が消せます。素晴らしい。 今のところ外部に公開してはいないのですが、外部に公開すると他のサービスとの連携(例えばIFTTT)ができないので、公開したい気持ちがあります。とはいえ、外からむやみに部屋の電気をあれこれされても困るし(だれもやらないとは思いますが)、そのまま公開するのも難しいな、と思っているところです。 とりあえずは扇風機とか、そのあたりをなんかいい感じにアレしたいですね。

2019-07-30 · nasa9084

zero memory allocation slice filtering

次のように、あるスライスをフィルタリングする関数を書くことがあると思います。 1 2 3 4 5 6 7 8 9 func FilterFoo(arr []string) []string { b := []string{} for _, e := range arr { if IsFoo(e) { b = append(b, e) } } return b } 簡単なベンチマークを書くとわかるように、この関数は返値となるスライスの長さ+1回のメモリアロケーションを行います。一般に、メモリアロケーションの回数は少ない方がパフォーマンスがよく、可能ならばアロケーション回数0を目指したいものです。 今回の場合、次のように書くとメモリアロケーション回数0回の関数を書くことができます。 追記 b := arr[:0]とすると、基底配列に影響が出るので一概に比較できない、とご指摘を受けました。実際に使用する際は副作用に注意しましょう。 このやりかたって引数に副作用あるので、わかってないで使うと危ないような…https://t.co/iKXrXHUD3N https://t.co/CMrAYGJrdA — Yoichiro Shimizu (@budougumi0617) February 4, 2019 append は引数を弄ってしまうので動作が異なりますね。 / “zero memory allocation slice filtering” https://t.co/JFFDJlfIQA — mattn (@mattn_jp) February 5, 2019 追記終わり 1 2 3 4 5 6 7 8 9 func FilterFoo(arr []string) []string { b := arr[:0] for _, e := range arr { if IsFoo(e) { b = append(b, e) } } return b } 違うのは一行目だけですが、ベンチマークを取ってみると、速度面では大きな違いがあります。次のようなベンチマークを実行してみます。...

2019-02-04 · nasa9084

jessevdk/go-assetsでファイルを埋め込む

Go言語の素敵なところの一つとして、最終的な成果物を1バイナリに収めることができる、という点にあると思う。結果として、非常に簡単にコマンドラインツールなどを配布することができる。 しかし、例えばコード生成を行うようなツールでテンプレートファイルを別途持っているような場合や、アプリケーション中で使う画像などを含む場合など、Goのソースコード以外のファイルを必要とする場合、全てを1ファイルで、とはいかない。 そのような場合に便利なのがjessevdk/go-assets である。以前は多くの人がgo-bindataを使用していたと思われるが、作者がやめてしまったため、使えなくなってしまった。代替としてこれが便利。 jessevdk/go-assetsを使用するには、まずjessevdk/go-assets-builder を使用する。これは、指定したファイルをGoのソースコードに埋め込んで、それらを扱うためのAssetsというオブジェクトを作成してくれるツールである。 インストールは簡単で、go getするだけ。 1 $ go get github.com/jessevdk/go-assets-builder インストールできたら、次のように使う。 1 2 3 $ ls assets/ foo.html.tmpl bar.png $ go-assets-builder assets -o assets.go すると、assetsディレクトリの内容が埋め込まれたassets.goが生成される。今回は特にパッケージ名を指定していないのて、package mainとして作成された。必要なら-pオプションでパッケージ名を指定することもできる。 生成されたあとは、実際に使いたいソースコード内で次のように使う。 1 2 3 4 f, _ := Assets.Open("/assets/foo.html.tmpl") // in production, need to handle error defer f.Close() // Do something with f ここで作成されたfはos.Fileと同じインターフェースを備えている。要するに、os.Openを使用したときと同じように操作することができる。 また、Assetsという変数を別に使いたいときは、go-assets-builderでパッキングするときに-vオプションで変数名を指定することもできる。ディレクトリ全体ではなく、個別のファイルを指定することもできる。

2019-01-17 · nasa9084

きちんとやるnet/http

皆さん、net/httpパッケージは使っていますか? Go言語の標準パッケージであるnet/httpはPythonなどの標準HTTPパッケージに比べ、人間にとっても取り扱いがしやすいため、そのまま使用している方が多いかと思います。 しかし、このnet/httpパッケージ、簡単に使えるように見えて結構落とし穴が多いのです。 1. Response Bodyはクローズする必要がある 次のコードを見てみましょう。 1 2 3 4 5 6 7 8 9 resp, err := http.Get("https://example.com/api") if err != nil { return nil, err } var t T if err := json.NewDecoder(resp.Body).Decode(&t); err != nil { return nil, err } return &t, nil クライアントライブラリなどでよく書きそうな処理ですね。何も問題ないと思いましたか? 公式ドキュメント を見てみましょう。 It is the caller’s responsibility to close Body. Bodyをクローズするのは関数を呼んだ人の責任、とあります。そうです。Response.Bodyは Close()しなければならないのです。ちゃんとクローズされていない場合、次のリクエストでkeepaliveコネクションの再利用がされず、パフォーマンスの悪化やコネクションリークを起こす可能性があります。 2. Response Bodyを最後まで読む Response Bodyをきちんとクローズするように修正したコードが次のようなコードです。 1 2 3 4 5 6 7 8 9 10 resp, err := http....

2019-01-08 · nasa9084

x/crypto/openpgpでデータを暗号化する

OpenPGPはPGP(Pretty Good Privacy)をベースとした暗号化フォーマットです。 Go言語でもgolang.org/x/crypto/openpgp という準標準パッケージで提供されています。 PGPは公開鍵暗号としてメールの暗号化等でよく使用されますが、パスフレーズを用いた対称暗号として使用することもできますので、今回はこちらを紹介します。 TL;DR 暗号化にはSymmetricallyEncrypt()を使用する 復号にはReadMessage()を使用する prompt次第で無限ループする恐れがあるので注意 暗号化 x/crypto/openpgpパッケージでパスフレーズを用いてファイルを暗号化するには、SymmetricallyEncrypt関数を使用します。 シグネチャは次のようになっています。 1 func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) 順番に見て行きます。まずは引数から。 第一引数であるciphertextには、暗号化されたテキストを出力するio.Writerを与えます。*os.Fileなどを与えてもいいですが、*bytes.Bufferなどを与えてその後*os.Fileにコピーする方が良いでしょう。可読なテキストではなく、バイト列が出力されます。 第二引数のpassphraseはその名の通り、パスフレーズを与えます。 第三引数のhintsには暗号化するファイルのメタデータなどを含むことができますが、単純にnilを与えても良いです。 第四引数のconfigで暗号化方式や乱数エントロピーソース、圧縮アルゴリズムなどを設定することができます。設定しなければ乱数としてcrypto/rand.Readerが、ハッシュ関数としてSHA-256が、暗号化関数としてAES-128が、現在時刻としてtime.Nowが、RSAのビット数として2048がそれぞれ使用されます。圧縮はされません。 返り値は二値で、io.WriteCloserとerrorです。返り値のio.WriteCloserに暗号化したい内容を書き込むことで暗号化が行われます。必ずCloseする必要があるので忘れないように注意しましょう。 使用例 1 2 3 4 5 6 7 8 func encrypt(in io.Reader, out io.Writer, passphrase []byte) error { // omit error handling w, _ := openpgp.SymmetricallyEncrypt(out, passphrase, nil, nil) defer w.Close() io.Copy(w, in) return nil } 復号 暗号化したファイルを復号するには、ReadMessage関数を使用します。Decrypt〜のような関数ではないので注意が必要でしょう。関数のシグネチャは次のようになっています。...

2018-11-26 · nasa9084

Generator Pattern

Generator PatternはGo言語における並列処理パターンの一つで、goroutine-safeな値列の生成などに使用することができます。 コードを見た方が早いと思いますので、コードを掲載しましょう。 次の例は複数のgoroutineから共通の連番を採番したいときに利用することができます。 1 2 3 4 5 6 7 8 9 10 11 12 13 func GenInt(ctx context.Context, max int) <-chan int { ch := make(chan int) go func() { defer close(ch) for i := 0; i < max; i++ { select { case <-ctx.Done(): return case ch <- i: } } return ch } 返された<-chan intからintの値を取得するようにすることで、重複のない連番を取得することができます。 Go言語において、chanは複数箇所から値の取り出しを行うことができますが、chanに入力された一つの値はどこか一箇所からしか取り出すことができません。そのため、lock等を使用しなくとも、必ず重複無く連番を取得することができます。 lockを使用した場合、若干動作が遅いため、可能であればlockを使用しないで、chanを使用して実装できるとより高速な、Goらしいコードとすることができます。

2018-11-21 · nasa9084

jessevdk/go-flagsでサブコマンドを実装する

Go言語を用いてコマンドラインツールを開発する際、皆さんはフラグのパースやサブコマンドの実装にどんなパッケージを使用していますか?標準のflagパッケージのほか、、spf13/cobra 、alecthomas/kingpin などもよく使われているようです。 私は専ら、jessevdk/go-flags (以下go-flags)を使用しています。 go-flagsはその名の通り、基本的にはオプション/フラグの解析用パッケージで、ドキュメント もフラグ解析に関するものがほとんどです。 しかし、go-flagsでは、サブコマンドの実装も可能です。今回はこれに焦点を当ててご紹介していきます。 go-flagsでは、親コマンドにサブコマンドを登録する、という形でサブコマンドを実装していきます。サブコマンドは構造体として実装し、それぞれがオプションを格納する構造体を兼ねる形となります。 終端の、実際に何かの動作をするコマンドは Commander interfaceを実装している必要がありますが、中間のサブコマンド(docker containerのような、グルーピングのためのサブコマンド)はこれを実装していなくても構いません。 Commander interfaceの定義は次のようになっています。 1 2 3 type Commander interface { Execute(args []string) error } 非常に単純ですね。argsにはコマンドでパースされなかったあまりの引数が渡されます。 実際の実装例を見てみましょう。 1 2 3 4 5 6 7 8 type subcommand struct { verbose bool `short:"v" long:"verbose"` } func (cmd *subcommand) Execute(args []string) error { // some exec return nil } サブコマンドを実装したら、親のコマンドにサブコマンドとして登録します。 ドキュメントを見ると、Command構造体に登録する関数があること、Parser構造体はCommand構造体が埋め込まれていること、がわかります。 通常、go-flagsパッケージを使用する場合はパッケージグローバルのParse関数を使用することが多いと思うのですが、サブコマンドを実装する場合はトップレベルのパーサーを自分で作る必要があります。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 type options struct { // ....

2018-11-06 · nasa9084

Future Pattern

Future Patternは非同期処理パターンの一つで、ある処理を別のスレッドなどで実行し、結果を後で(=未来で)受け取るような処理に用いられるデザインパターンです。 特徴としては、外側に見えている関数などの処理を実行するオブジェクトは、処理を別スレッドに委譲し、後で結果を得ることの出来るFutureと呼ばれるオブジェクトを即座にメインロジックへと返却することです。 言葉で書いても、何だかよくわからないので、コードを見てみましょう。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 /* package, import part */ func main() { in := make(chan int) out := Double(in) // この時点では結果は得られない go func() { for i := 0; i < 10; i++ { in <- i } close(in) }() for d := range out { fmt....

2018-07-04 · nasa9084

array/sliceに対する存在確認関数のベンチマーク

Pythonでいうところの、次の様な条件式を実現する関数を書きたかった。 1 2 3 4 5 ls = ["foo", "bar", "baz"] s = "baz" if s in ls: print("FOOBAR!") 対象がリストの時、普段なら普通にfor文を回すのですが、今回やりたかったのは定数値の一覧にあるかどうか、だったのと、定数の数も少なかったので、とりあえずで以下の様に実装していました。 1 2 3 4 5 func something(s string) error { if s != "foo" && s != "bar" && s != "baz" { return errors.New("value invalid") } } 流石に雑すぎるので、リファクタリングしよう、と思ったのですが、「はて、for文挟んだら遅くなったりしないだろうか」などと考えてしまったのでベンチマークを取りました。 TL; DR 素直にfor文を回しても大して問題はなさそう result 今回取ったベンチマークは6種類です。 for-range文を回す for文を回す map[string]struct{}を集合として取り扱ってみる &&, ||でつなぐ switch文を使う sort.SearchStrings()を使う 6番目のsort.SearchStrings()を使う方法はstackoverflow に書いてあった方法で、二分探索をしてくれるというのでやってみました。 結果は次の通り。 BenchmarkInByForRange-4 200000000 9.34 ns/op 0 B/op 0 allocs/op BenchmarkInByFor-4 100000000 10....

2018-06-26 · nasa9084