2018年 10月の投稿を表示しています

Go言語のスイッチが一瞬わからなくなったのメモ

一瞬わからなくなったのでメモ。
https://play.golang.org/p/AmpjLMDFPf8

そもそも型スイッチは interface{} は値を任意の型になっているか確認して、その型にキャストされた状態にしてくれるすごいやつ。
A Tour of Go に出てくるので知っている人も多いハズ。
Type switches

Go なりの型の持ち方、ようはダックタイピングをイマイチちゃんと使ってなかったのもあって理解ができてなかったが
"値がこういうものを持っていたらこの型だよね" という話なだけと、とりあえずのところは理解した

ある値が String() な関数を持っている interface{} ならそれは fmt.Stringer() を満たしているのでキャストができるし
他にも String() だけを要求する interface があれば、それを満たしているともいえるので、その型キャストが出来る。

 

あと混乱をきたすので深掘りせずにイイ感じに応対したいんだけど、そこにポインタが絡んでくると謎っぽい。

https://play.golang.org/p/MHIX7i1Royk

まあ、特に理由がなければ struct の扱いはポインタでよいんじゃないだろうか。
CodeReviewComments にも怪しかったらポインタレシーバを使うのだって書いてあった。
CodeReviewComments · golang/go Wiki · GitHub

 

話がそれてきたのでおわり。

モバイル端末の傾きを JavaScript で受け取る

Device Orientation API というものを JavaScript から触ることで、デバイスの傾きを取得することができる。

デスクトップ PC だとかノート PC だとか、あるいはタブレットとかそのほかモロモロの端末でも加速度センサーがサポートしていれば Chrome なり Firefox なりブラウザがよしなに対応してくれているはず。

Detecting device orientation - Web API reference | MDN

Can I use... Support tables for HTML5 CSS3 etc

ちょっと気になったのだけど W3C の TR を見たら、メンテしないぜ!的なことが書いてあって!?!?な感じ。

DeviceOrientation Event Specification

加えて Geolocation Working Group なのもちょっと不思議な気がしたのだけど、これはきっと、デバイスの傾きを取るというのが本題ではなくて、方角や座標系をいい感じにとるための API なり仕様なりを定めようとしていたのかもしれない、という推測。

 

話を戻して W3C の仕様は少し怪しいものの Can I Use を見る限りはなんとなく幅広いブラウザで一部サポートがされている。でもって MDN を見ると使い方が書いてある。

ざっくりとはこういう形で値を取得することができる。
ようは傾きに応じてイベントがバシバシ発行されるからそれを各自拾ってくれスタイル。

window.addEventListener('deviceorientation', function(event) {
    console.log({
        beta: event.beta   // x 軸
        gamma: event.gamma // y 軸
        alpha: event.alpha // z 軸
    })
});

これをお試すべく、ちょっと計算が間違っている…というか 3 次元の傾きを 2 次元に投影するっていうのがよくわかんないので
若干適当になったものの、ごみばこいんのトップページをスマホで開いたときに傾きを使って重力をコントロールできるようにした。

モバイル端末からお試しあれ。

 

余談になるけど Chrome の DevTools からセンサーのエミュレーションもできることに気づいた。
More Tools から Sensors を開く。

こういうものが見えるようになるので Orientation のところでドロップダウンリストから選んだり、スマホの形状をしているものをドラッグしてぐるぐる回して 遊べる 回転を調整したものを Chrome がエミュレーションしてくれる。

 

ちなみにちなみに、すでにページを開いている状態からこの Sensors のエミュレーションをしようとすると以下のような文言が出てくる。

A reload is required so that the existing AbsoluteOrientationSensor and RelativeOrientationSensor objects on this page use the overridden values that have been provided. Close the inspector and reload again to return to the normal behavior.

これはそのままページをリロードすれば解決する。
冷静に考えて動的にデバイスのエミュレーションを差し込むってすげー大変だと思うよ。

zapcore.Field を生成する関数を自分で定義する

uber-go/zap: Blazing fast structured leveled logging in Go.

zap を使ってログを出すときに自分でフィールドを追加できる。

こういう雰囲気で。

logger.Info(
    "invalid address",
    zap.String("address" address)
)

このとき zap.String って書いているけど、これを自分で定義できるのかな?と zap のソースコードを読んだりしてたらできそうなことがわかった。
でもって試したのが、これ。

sters/zap-hashed-field: Define hashed zapcore.Field

具体的なユースケースがわからんけど、例えば入力されたデータをもとに動きを追いかけたい、とか、なにがしかの都合で、センシティブなデータ(パスワード、メールや電話番号、トークン値、…etc)を出したいときがある、と思う。そういうときに使えるんじゃね?的な妄想をしながら作った。

こういう風に使ってハッシュ値にして出力できる。

logger.Info(
    "invalid address",
    hashedfield.Sha1("address" address)
)

 

これをどうやってやるかっていうと、単に zapcore.Field が構造体になっているので、それを生成して zap.Logger で出力する場所に渡してあげるだけでよかった。

zapcore.Field は以下のようなフィールドを持っている。
zap/field.go at master · uber-go/zap

type Field struct {
	Key       string
	Type      FieldType
	Integer   int64
	String    string
	Interface interface{}
}

このとき Type に指定したものに応じて zap.Logger がよろしく値を変換して出力してくれる。文字列を出したいなら StringType を指定して String フィールドに値を入れればよい。
zap.String がまさにそう。
zap/field.go at master · uber-go/zap

func String(key string val string) Field {
	return Field{Key: key Type: zapcore.StringType String: val}
}

 

使い方のサンプルってどうやって書いたらいいのかなあと思いながら zap のコードを眺めていたら
examples_test.go というファイルがいて、なんだろうな、と。

zap/example_test.go at master · uber-go/zap

そこから調べてたら Examples Test を知った。

Testable Examples in Go - The Go Blog

要するに、テストコードの最後に期待する出力をコメントで書いておくと出力を内部でハンドリング、比較して様子を見てくれるとのこと。
便利~~~~。