Shogo's Blog

Aug 19, 2018 - 1 minute read - go golang wasm

GoAst ViewerをWebAssemblyへビルドしてみた

もうすぐリリースのGo1.11ではWebAssemblyのサポートが予定されています。 (2018/08/19現在の最新版はGo1.11rc1) Go言語がWebAssemblyをサポートへ。GOARCHは「wasm」、GOOSは「js」に 正式リリース前に少し遊んでみようということで、@yuroyoroさんのGoAst ViewerをWebAssemblyへビルドしてみました。 GoAst Viewer WebAssembly Version shogo82148/goast-viewer JavaScriptの連携方法 コードをASTに変換し、JSONとしてエンコードする部分(ast.go)に関しては、一切変更しなくても動きました。素晴らしい。 ただし、さすがにブラウザ上でHTTPサーバーは動かない(そういえば試してないけど、動かないよね??)ので、JavaScriptとの連携部分を実装してあげる必要があります。 syscall/jsパッケージはまだ実験段階というステータスで機能が限られているので、 連携には少し工夫が必要です。 JavaScriptからGoの関数を呼ぶ JavaScriptからGoの関数を呼ぶには window にコールバック関数として必要な関数を登録します。 // GoASTParse 関数を定義(Go言語) js.Global().Set("GoASTParse", js.NewCallback(func(args []js.Value) { source := args[0].String() // ...ASTへの変換処理... })) 戻り値をGoからJavaScriptへ返す js.NewCallback なのですが、もともとは addEventListener にわたすコールバック関数なので、 関数の戻り値を受けわたす方法がありません。 回避方法はいろいろあるでしょうが、今回はコールバック関数の引数にコールバック関数指定してもらうことにしました。 // GoASTParse 関数を定義(Go言語) js.Global().Set("GoASTParse", js.NewCallback(func(args []js.Value) { source := args[0].String() // ...ASTへの変換処理... args[1].Invoke(string(body)) })) // GoASTParseを呼び出す(JavaScript) GoASTParse("package main; func main() {}", function(body) { // ASTの表示処理 }) まとめ Goのバイナリ全般に言えることですが、WASMになってもやっぱりサイズが大きい(3.5M)。 今後のパフォーマンス向上に期待です。 GoよりAngulerJSの方が難しかったʕ ゚皿゚ ʔ

Aug 11, 2018 - 1 minute read - javascript time

Web JJY が夏時間に対応しました

サマータイムなんて日本人には関係ないと思っていた時期が僕にもありました。 ところが何やら日本にもサマータイムがやってくる動きがあるようです。 酷暑対策でサマータイム導入へ 秋の臨時国会で議員立法 31、32年限定 さて、長波JJY(市販の電波時計のための電波)には夏時間の情報が含まれています。 「将来の拡張性のための予備ビット」という扱いなので、対応している時計なんてないだろう、と思っていたら、 なんと対応している時計が存在しているらしいということを知りました。 その事実を確かめるため、Webブラウザを使って電波を出してみたで紹介した JJYシミュレータWeb版に夏時間を有効にするチェックボックスを追加しました。 CITIZEN 8RZ152 の動作例 夏時間への同期、完了しました 😂😂😂 pic.twitter.com/3tMcCYdXpP — Ichinose Shogo (@shogo82148) 2018年8月9日 念の為書いておきますが、今は午前8時です — Ichinose Shogo (@shogo82148) 2018年8月9日 DST(Daylight Saving Time)の表示が出て、夏時間に切り替わったことがわかりますが、なぜか6時間もズレています・・・。 もう、こんな時間だ……そろそろ寝よう…… ???お前24時間表記だっただろ?どうしたんだ??? (今は20時です) pic.twitter.com/8PViLOaj85 — Ichinose Shogo (@shogo82148) 2018年8月10日 悲報 11日を迎えることができず pic.twitter.com/pw0k0Qo8RY — Ichinose Shogo (@shogo82148) 2018年8月10日 もはや数字ではないものが出てきた。 まとめ 夏時間に対応した電波時計の存在は事実でした。 しかし、機種によっては挙動がおかしくなるようです(N=1)。 ぜひ、みなさんもお手元の電波時計で試してみてください! JJYシミュレータWeb版 ※ 利用の結果生じた損害について、一切責任を負いません。 参考 標準電波の出し方について 酷暑対策でサマータイム導入へ 秋の臨時国会で議員立法 31、32年限定 Webブラウザを使って電波を出してみた サマータイムで日本中の電波時計がゴミになる(かも)という話 サマータイム導入で「電波時計が狂う」? メーカーに聞いた 「サマータイム導入はコンピュータシステム的に難あり」は本当か サマータイム実施は不可能である from UEHARA, Tetsutaro 僕もサマータイム実施は不可能だと思います・・・。

Jun 20, 2018 - 1 minute read - go golang

S3からファイルを落とすだけのツールを作った

S3からファイルを落とすだけのツールを作りました。 s3cli-mini 目的 流行りのCD(継続的デリバリー)を実践するために、専用のデプロイツールをダウンロードする目的で作りました。 主なデプロイ先はAWSなので、デプロイ操作には awscli が必要です。 しかしCDに使用しているCircleCIが公式に提供しているコンテナイメージにはawscliがインストールされていません。 もちろん apt-get install awscli であとからインストールすることは可能ですが、そのぶんジョブの実行時間が長くなってしまいます。 また、インストールされる awscli のバージョンが古く、ローカル環境ではうまく動くけど、 CircleCI上では最新の機能が使えず失敗するということがありました。 そこでもう awscli を使うことは諦めて、Goで AWS API を叩いてデプロイするバイナリを作ってしまうことを考えました。 Goであればシングルバイナリでインストール可能で、CI/CD環境とローカルでバージョンが一致せず悩まされることはありません。 また並行処理が得意なので、デプロイの時間短縮も図れます。 しかし、このデプロイ用のバイナリをどこに置くか・・・プロジェクト固有の処理が入っているので外部には公開したくない。 かといってプライベートなS3バケットに置くと、ダウンロードに awscli が必要になってしまう・・・。 awscli を使うのは諦めたはずでは・・・という、いわゆる「鶏が先か、卵が先か」問題に陥ってしまいました。 そこでS3からのダウンロードの処理に特化したミニawscliが欲しくなって作成したのが s3cli-mini です。 使い方 現状v0.0.1でサポートしているのは cp コマンドのみです。 S3バケットからファイルをダウンロードしたり、S3バケットへファイルをアップロードしたり、 別のS3バケットへファイルを転送することができます。 # download from a S3 bucket s3cli-mini cp s3://your-bucket/foobar.zip . # upload to a S3 bucket s3cli-mini cp foobar.zip s3://your-bucket/ # copy the file from a S3 bucket to another S3 bucket.

Jun 9, 2018 - 1 minute read - go golang

GoでHTTPとS3を透過的に扱う

Goの http.Transport には RegisterProtocol というメソッドが生えていて これを使うと、 HTTP以外のプロトコルを透過的に扱うことができます。 代表的なのは http.NewFileTransport で、これを使うと、file://path/to/file.txt みたいなURLでファイルにアクセスすることができます。 (Goオフィシャルの例) この仕組を使って、S3へのアクセスも透過的にできるようにしてみたので、メモ。 新しいプロトコルを作成するのは非常に簡単です。 http.RoundTripperインターフェースを実装し、リクエストに応答するレスポンスを作ってあげればいいだけです。 S3の場合以下のようになります。(エラー時の扱いが雑だけど・・・) package main import ( "net/http" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" ) type s3RoundTripper struct { s3 *s3.S3 } func newS3RoundTripper(session *session.Session) http.RoundTripper { return &s3RoundTripper{ s3: s3.New(session), } } func (rt *s3RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { host := req.Host if host == "" { host = req.URL.Host } path := req.URL.Path ctx := req.Context() out, err := rt.

May 16, 2018 - 2 minute read - go golang

Goの構造体のコピーを防止する方法

去年仕込んだネタが見つかってしまったので、macopy 構造体について一応解説。 https://t.co/mHq6oWY3rj macopyさん構造体だったのか・・・ — serinuntius (@_serinuntius) 2018年5月14日 2021-05-25 追記 今はこの方法では動かないというツイートを見かけました。 これで出てくる "Goの文法を使った構造体のコピーを防ぐ方法" が動かなかった話ですが https://t.co/FpEnspIfmN このへんに書いてありました.重要なことはその型がstructであること,Lock だけでなく Unlockも実装されていることでした.https://t.co/zQc6T058Ip このように変更すると検知されました — おりさの (@orisano) May 25, 2021 どうやら Go 1.11 から判定基準が 「sync.Locker を実装しているか」に変わっていたようです。 (修正コミット: c2eba53, Issue: #26165) というわけで、 macopy 構造体を以下のように変更する必要があります。 type macopy struct{} func (*macopy) Lock() {} func (*macopy) Unlock() {} 追記ここまで 目的 深淵な理由で Go の構造体のコピーを禁止したい場合があると思います。 kuiperbelt のケースでは、sync/atomic パッケージを使ってフィールドを更新しているので、 フィールドへの読み書きは必ず sync/atomic パッケージを使わなければなりません。 sync/atomic パッケージを使わずに構造体をコピーするとレースコンディションが発生してしまうので、コピーを禁止する必要がありました。 // https://github.com/kuiperbelt/kuiperbelt/blob/e3c1432ed798716c8e88183518f9126951c227f3/stats.go#L20-L28 type Stats struct { connections int64 totalConnections int64 totalMessages int64 connectErrors int64 messageErrors int64 closingConnections int64 noCopy macopy } // atomic.

Apr 10, 2018 - 2 minute read - hugo go golang

OctopressからHugoに乗り換えた

OctopressからHugoに乗り換えました。 以下のような理由からです。 Rubyの環境をメンテナンスし続けるのが面倒 最近Octopress自体の更新が滞っている ビルド時間が長い 一番最初の理由が大きくて、いつもビルドしていた環境を壊してしまって修復が面倒になってしまいました。 そこでようやく重い腰を上げて移行したというわけです。 移行手順 OctopressからHugoへの移行は先人たちがたくさんいるので、それを参考にします。 # 記事のコピー cp octopress-site/source/_posts/* hugo-site/content/post/ # 画像のコピー cp -r octopress-site/source/images/* hugo-site/static/images/ # 記事のタイムスタンプの形式を変える # Hugoでは、"2016-09-25T15:09:57"のような形式のタイムスタンプでないとパースに失敗します find . -type f -exec sed -i "" -e 's/date: \([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\) \([0-9]\{2\}:[0-9]\{2\}\)$/date: \1T\2:00+09:00/g' {} \; パーマネントリンクを維持するために OctopressからHugoへ移行する方法 のRubyスクリプトを利用させていただきました。 dir = 'content/post/' Dir::foreach(dir) do |filename| if filename =~ /\.markdown$/ slug = filename.gsub(/\d{4}-\d{2}-\d{2}-/, '').sub('.markdown', '') puts "#{filename} : #{slug}" lines = [] File::open(dir + filename) do |f| f.each do |line| lines << line end end File::open(dir + filename, 'w') do |f| lines.

Jan 2, 2018 - 1 minute read - mackerel

Mackerel AWS Integration 用の CloudFormation テンプレートを書いた

昨年の年末から Mackerel の本格導入を始めました。 それに当たって AWS Integration 用の CloudFormation テンプレートを書いたので、 他のプロジェクトでも導入が簡単になるよう公開しました。 shogo82148/cf_mackerel 使い方 GitHub Pages でテンプレートを公開しているので、 template-body にテンプレートのURLを指定して、 新しいスタックを作成するだけです。 aws cloudformation create-stack --stack-name "MackerelIntegrationIamUser" \ --template-body https://shogo82148.github.io/cf_mackerel/mackerel.yaml \ --capabilities CAPABILITY_NAMED_IAM 新しい名前付きIAMロールを作成するので CAPABILITY_NAMED_IAM が必要です。 作成がうまくいくとOutputに以下のようなARNが出力されるので、 MackerelのAWS Integrationの設定画面へ入力しましょう。 arn:aws:iam::xxxxxxxxxxxx:role/MackerelAWSIntegrationRole-ap-northeast-1 ロール名について ロール名が意図せずに変わってしまって連携が切れてしまうのを防ぐため、 ロール名は決め打ちです。 MackerelAWSIntegrationRole-ap-northeast-1 ロール名にリージョン名(この場合は ap-northeast-1)が含まれていますが、 作成されたロールはグローバルなリソースなので、他のリージョンでも使用可能です。 わざわざリージョン名含めているのは CloudFormation の警告にしたがったためです。 警告 IAM リソースに名前を付けると、複数のリージョンで同じテンプレートを再利用した場合に、回復不能なエラーが発生する場合があります。 これを防止するために、Fn::Join と AWS::Region を使用して、次の例のように地域固有の名前を作成することをお勧めします RoleName 回復不能なエラー!! コワイので実際に何が起こるかは試してませんが、警告には素直に従っておくことにします。 参考 AWS::IAM::Role - AWS CloudFormation - mackerelのAWSインテグレーション用IAM Userをcloudformationで作る Tomohiro/tf_mackerel 同じことをするTerraformのモジュール

Dec 6, 2017 - 2 minute read - aws-lambda python mecab

MeCabをAWS Lambdaで動かす(2017年版)

AWS Lambda上で鯖(Mackerel)の曖昧性問題を機械学習で解決しようの記事の中で、 Lambda上でMeCabを動かすことについて以下のように触れられています。 日本語を扱う自然言語処理ではMeCabを扱うことが多いですが、Lambda上でMeCabを動かすのは一手間必要なようです。 確かにLambda上でMeCabを動かすのは一手間必要です。 しかし、参照している記事は少し古くて、今はもう少し手軽にできるようになっています。 ブコメでも言及しましたが、改めて記事として残しておこうと思います。 ビルド方法(2017年版) 結論から言うと Norio Kimura さんのコメント 通りにビルドするのが、2017年12月現在一番楽な方法です。 (お返事すっかり忘れていてスイマセン・・・情報提供ありがとうございます) 調べてみると、AWS Lambda では環境変数 LD_LIBRARY_PATH が既に設定されていて /var/task/lib を含んでいました。元記事で ./configure –prefix=$PROJECT_HOME/local ではなく ./configure –prefix=$PROJECT_HOME とすればライブラリとの動的リンクは何もしなくても実現できます。さらにコードが展開されるディレクトリ /var/task を固定値だと決め打ちして PROJECT_HOME を /var/task にして開発すれば MeCab に渡すパラメーターの設定(-d, -r)も不要になります。undocumented な仕様に2つも依存していて気持ち悪いですが、MeCab を呼ぶ側のコードを Lambda 用に変更する必要がなくなります。 コメント中の元記事というのは、こちらの記事のことです。 AWS Lambda で MeCab を動かす export PROJECT_HOME=/var/task # LAMBDA_TASK_ROOT # 1. プロジェクト用にディレクトリを作成 mkdir -p "$PROJECT_HOME" # 2. MeCabのダウンロードとインストール # googlecodeサービス終了に伴い、ダウンロードURLが元記事と変わっていることに注意 cd "$HOME" curl -fsSL "https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE" -o mecab.tar.gz cd mecab-0.996 .

Oct 28, 2017 - 2 minute read - go golang

Go言語の浮動小数点数のお話

元ネタ: [JavaScriptの問題] var a = 0.3 - 0.2; var b = 0.2 - 0.1; var c = a==b; cの中身はどれ? — RAO(らお)@けもケP-31 (@RIORAO) 2017年10月24日 正確な実数計算をやらされるJavaScriptくん #擬竜戯画 pic.twitter.com/ipE56C2YbV — RAO(らお)@けもケP-31 (@RIORAO) 2017年10月26日 コンピューターで浮動小数点数を扱ったことのある人なら一度は経験する、 数学上の計算とコンピューター上の計算が合わない計算の一例ですね。 この件に関して、Go言語では正しく(=数学的な結果と同じように)計算できるとの情報が。 おそらくGoはコンパイラがa=0.1とb=0.1に変換していると思われます。 添付した画像のコードだとtrueになりますが、constをvarに変更するとfalseになります。constはコンパイル時に計算されますが、varは実行時に計算されるためです。 pic.twitter.com/LpKZF2kOjH — morikuni (@inukirom) 2017年10月27日 しかしながら、inukiromさんのこの推察、半分はあってますが、半分は間違っていると思います。 なぜGo言語でこのような結果になったのか、検証してみました。 Goの数値定数の型について 以前Go言語でコンパイル時フィボナッチ数列計算で紹介した Better C - Go言語と整数 #golangにもあるように、 Goの定数には「型がない(場合がある)」「任意の精度で計算してくれる」という特徴があります。 このため、普通はどう考えてもオーバーフローしそうなこんな演算も・・・ package main import ( "fmt" ) func main() { var i uint64 = 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 % 1000000007 fmt.Println(i) } play.golang.org/p/FkMVpY2Fa3 型がない定数同士の演算は 162132938 と正しい答えを出してくれます。

Oct 22, 2017 - 2 minute read - go golang

ACMのドメイン検証をシミュレートするやつ書いた

始まりは一件のメールから。 Title: Action Required - Your certificate renewal Greetings from Amazon Web Services, You have an AWS Certificate Manager (ACM) provided SSL/TLS certificate in your AWS account that expires on Nov 04, 2017 at 12:00:00 UTC. That certificate has the following domains: example.com, *.example.com AWS account ID: xxxxxx AWS Region name: us-east-1 Certificate identifier: arn:aws:acm:us-east-1:xxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Therefore, ACM has initiated the process to renew this certificate. You must take the action below before Nov 04, 2017 at 12:00:00 UTC to avoid certificate expiration, which might cause your website to become unreachable.