20210405のGoに関する記事は4件です。

Protocol Buffersの定義をMarkdownで出力するためのカスタムテンプレートを作った

モチベーション 現在のプロジェクトではProtocol Buffersの定義ファイルは画面が必要としている関心事ごとに サービスが分割されており1サービスが1つのpackageに紐づくよう設計されています。 そのためProtocol Buffersは以下のような以下のような複数ファイル構成になっています。 src └ proto   └ app     ├ user     │ └ user.proto     ├ comment     │ └ comment.proto     └ search       └ search.proto リクエストパラメータのvalidationもProtocol Buffers上で定義されており、現在mwitkow/go-proto-validators と envoyproxy/protoc-gen-validate が使用されています。 このvalidationの閾値をProtocol Buffersを設計しているバックエンダー以外へ連携する際に そのままprotoファイルを見せても分かりにくいので、1つのMarkdownにまとめてドキュメント化しようというのが今回やりたかったことです。 Protocol Buffersをドキュメント化する事自体はpseudomuto/protoc-gen-doc というlibraryで既に提供されているためこちらを使用します。 しかし、デフォルトの状態で出力されるMarkdownファイルはファイル毎に分割されてしまう上にそもそもvalidationの設定が出力されないためカスタムテンプレートを用意することにしました。 作成したもの 以下のテンプレートを作成しました。 https://gist.github.com/tomtwinkle/074bfc9cd4db53b58bb4ff368157f3ed 使い方としては src ├ proto │ └ app │   ├ user │   │ └ user.proto │   ├ comment │   │ └ comment.proto │   └ search │     └ search.proto └ custom_markdown.tmpl # <--- custom template のように配置し --doc_out にドキュメントの出力先、--doc_opt にテンプレートの設定とファイル名を追加して protoc を実行します。 cd src protoc -I . -I <validatorのパス> --proto_path=proto --doc_out=../docs --doc_opt=custom_markdown.tmpl,doc.md ./proto/app/**/*.proto src ├ proto │ └ app │   ├ user │   │ └ user.proto │   ├ comment │   │ └ comment.proto │   └ search │     └ search.proto ├ custom_markdown.tmpl # <--- custom template docs └ doc.md # <--- generate markdown document コードジェネレートとセットで行うことも出来ます。 例えばgolangとgrpc-webのコードジェネレートとセットで行う場合は以下のようになります。 protoc -I . -I <validatorのパス> --proto_path=proto --doc_out=../docs --doc_opt=custom_markdown.tmpl,doc.md --proto_path=proto --go_out="plugins=grpc:../go" --validate_out="lang=go:../go" --grpc-web_out=import_style=commonjs+dts,mode=grpcwebtext:../web --js_out=import_style=commonjs:../web ./proto/app/**/*.proto おまけ:validatorのパスを書きたくない Protocol Buffersの定義をMarkdownで出力するネタとは全然関係ないですが validatorをProtocol Buffersで定義する場合どうしてもvalidator自身のproto fileのパスをprotocに読ませる必要があるため GO111MODULE=off go get github.com/envoyproxy/protoc-gen-validate protoc -I $GOPATH/src/github.com/envoyproxy/protoc-gen-validate みたいな手順を開発環境の構築手順に加えてあげる必要が出てきてしまいます。 go getしてくるpackageは開発者毎に異なる可能性があり環境差分が生まれる原因ともなります。 解決するためにはProtocol Buffersのソース内にvalidatorのpackage名のディレクトリを掘りvalidator自体のprotoファイルをライセンスファイルとセットで置いてあげるのが良さそうです。(Apache License 2.0なので) protoファイルを取り込む場合はそれぞれのvalidatorのライセンスをよく確認してください。 src ├ proto │ ├ app │ │ ├ user │ │ │ └ user.proto │ │ ├ comment │ │ │ └ comment.proto │ │ └ search │ │   └ search.proto │ └ github.com # <------ validator proto files │   ├ envoyproxy │   │ └ protoc-gen-validate │   │   ├ validate │   │   │ └ validate.proto │   │   ├ LICENSE │   │   └ NOTICE │   └ mwitkow │     └ go-proto-validators │       ├ validator.proto │       └ LICENSE.txt ├ custom_markdown.tmpl docs ├ doc.md go web 使うvalidatorが envoyproxy/protoc-gen-validate だけで良いなら mwitkow/go-proto-validators のディレクトリは不要です。逆もまた然り。 validatorを使用したいprotoファイル内では以下のようにimportします。 import "github.com/envoyproxy/protoc-gen-validate/validate/validate.proto"; package名と同じディレクトリを作成することにより Before protoc -I . -I <validatorのパス> <build options> ./proto/app/**/*.proto と参照パスをオプションで指定する必要があったものが After protoc <build options> ./proto/app/**/*.proto だけでbuild出来るようになります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Go 1.11 の go mod download を速くする

Go 1.13 から Go module mirror と Go checksum database が導入され go mod download が高速化されました。 しかし Go 1.11 ユーザーはこの恩恵を受けられません。 そこで Go 1.11 の go mod download を速くするために試した結果をご紹介します。 短い結論 プライベートリポジトリに対する依存がない場合は環境変数 GOPROXY に https://proxy.golang.org を設定する。 プライベートリポジトリに対する依存がある場合はモジュールダウンロードを Go 1.13 にやらせる。 測定方法 golang:1.11 の docker コンテナ内で golangci-lint を git clone したのち time go mod download を 3 回実行して最も速かった時間を記録しました。 また time go mod download 実行前に go clean -modcache でキャッシュをクリアしています。 $ export GO111MODULE=on $ git clone https://github.com/golangci/golangci-lint.git $ go clean -modcache $ cd golangci-lint $ time go mod download golangci-lint を使用したのは GitHub でホストされている多数の外部パッケージ (linter) に依存しており go mod download の速度を調べるのに適していると考えたからです。 ※ Go 1.11 でも golangci-lint のモジュールダウンロードはできますがビルドはできません。 試した方法 デフォルト (HTTPS) 何も設定せずに go mod download を行いました。 Go 1.11 の go mod download は HTTPS で各パッケージのリポジトリからデータを取得します。 GOPROXY しかし Go 1.11 ユーザーはこの恩恵を受けられません。 冒頭に上記のように書いたのですが実は Go 1.11 でも 環境変数 GOPROXY を設定することで Go module mirror を利用できます。 $ export GOPROXY=https://proxy.golang.org 紹介した Go Blog の記事 にも次のように書かれています。 If you are running an earlier version of the go command, then you can use this service by setting GOPROXY=https://proxy.golang.org in your local environment. ただし Go 1.13 以降と異なり、次の点に注意が必要です。 環境変数 GOPROXY にカンマを含めることができません。 環境変数 GOPRIVATE をサポートしていません。 これらの違いはプライベートリポジトリに対する依存がある場合に問題になります。 SSH GitHub への接続に SSH を使用する設定を行いました。 SSH や git の設定についてはあちこちで紹介されているので省略します。 今回は次のように GitHub でホストされているすべてのリポジトリが対象となるように設定しました。 $ git config --global url."ssh://git@github.com/".insteadOf "https://github.com/" $ cat .gitconfig [url "ssh://git@github.com/"] insteadOf = https://github.com/ SSH (ControlMaster auto) GitHub に対する SSH 接続を使いまわす設定を追加しました。 ControlMaster auto ControlPath ~/.ssh/sockets/%r@%h-%p ControlPersist 10 設定している内容については ControlMaster で検索すると記事が見つかると思います。 Go 1.13 併用 モジュールダウンロードを Go 1.13 にやらせるという方法です。 Go 1.13 は次の手順でインストールしました。 .tar.gz ファイルを直接ダウンロードして適切な場所に展開してもよいと思います。 $ go get golang.org/dl/go1.13.15 $ go1.13.15 download インストールすると go1.13.15 コマンドが利用できるようになります。 $ go1.13.15 clean -modcache $ time go1.13.15 mod download 環境変数で明示的に設定していない場合 Go 1.11 と Go 1.13 はモジュールキャッシュを共有しているため go1.13.15 mod download を実行後に go mod download を実行してもダウンロードは発生しません。 共有しても大丈夫なのかという疑問はあると思いますがモジュールキャッシュはダウンロードしたファイルの格納場所であるとドキュメントに記載されています。 Go 1.15 のリリースノートにも次のような記載があるので異なるバージョンの Go がキャッシュを共有することは想定内だと考えています。 The workaround is not enabled by default because it is not safe to use when Go versions lower than 1.14.2 and 1.13.10 are running concurrently with the same module cache. 結果 ネットワーク帯域が安定していなかったり測定した時間が異なるので精度は低いものと考えてください。 実行方法 処理時間 (秒) デフォルト (HTTPS) 332.753 GOPROXY 28.808 SSH 384.548 SSH (ControlMaster auto) 379.934 Go 1.13 併用 94.846 GOPROXY すごい。 GOPROXY と Go 1.13 以外は PC の調子が悪かったのか回線が貧弱だからか途中でエラーになってしまうため成功するまで go mod download を繰り返しました。 記載している処理時間は成功するまでに実行した go mod download の合計になります。 SSH は HTTPS より遅い結果になりました。 残念ながら ControlMaster auto 設定もあまり効果がないようです。 (設定不備あるいは GitHub 側の制限の可能性もあります) Go 1.11 (GOPROXY) と Go 1.13 の違いがどこで出ているのかも分かってません。 まとめ プライベートリポジトリに対する依存がない場合は環境変数 GOPROXY に https://proxy.golang.org を設定することで Go 1.11 による go mod download が大幅に高速化されることがわかりました。 また、プライベートリポジトリに対する依存がある場合でもモジュールダウンロードを Go 1.13 で行うことで Go 1.11 のみより短時間でダウンロードできることがわかりました。 この記事が GAE/Go 1.11 に魂を縛られている同志 1 のお役に立てば幸いです。 https://cloud.google.com/appengine/docs/standard/go/go-differences ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

電力密度の計算方法

携帯電話の基地局から発射される電力密度の計算方法です。 等方(アイソロロピック)アンテナとしての計算です。 これは、1点から球状に電波が広がっていくとしたモデルです。 S: 電力密度 W/m^2 P: 電力 W (ワット) r: 距離 m S = P / (4 * pi * r^2) 計算例 電力 640W , 距離 5 m の場合 Node.js の例 $ node Welcome to Node.js v15.13.0. Type ".help" for more information. > 640 / (4 * Math.PI * 5**2) 2.0371832715762603 > TypeScript の例 $ npx ts-node > 640 / (4 * Math.PI * 5**2) 2.0371832715762603 Deno の例 $ deno Deno 1.0.0 exit using ctrl+d or close() > 640 / (4 * Math.PI * 5**2) 2.0371832715762603 python3 の例 $ python3 Python 3.9.2 (default, Feb 20 2021, 18:40:11) [GCC 10.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import math >>> 640 / (4 * math.pi * 5**2) 2.0371832715762603 >>> Go の例 $ gore gore version 0.5.2 :help for help gore> :import math gore> 640.0 / (4.0 * math.Pi * math.Pow(5.0,2.0)) 2.037183 2.04 W/m^2 は、0.204 mW/cm^2 になります。 参考、  日本の規制値は、0.1 mW/cm^2  ICNIRP の規制値は、0.09 mW/cm^2 指向性のアンテナの場合は、強い方向への補正と、弱い方向への補正が必要です。 コンクリートの壁などがあれば、弱い方向への補正が必要です。 コンクリートによる減衰は、材質、厚さにより異なります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Raspberry Piをスイッチでシャットダウンする

Raspberry Pi にログインすることなく外部からのボタン入力でシャットダウンさせます。実装はgo言語です コードはGithubにも公開しています 動作環境 HW: Raspberry Pi 4B OS: Ubuntu server 20.04 64bit 配線接続 GPIO2とGroundをメカニカルスイッチに接続する(ピンアサイン図) コード main.go package main import ( "fmt" "log" "os/exec" "time" "periph.io/x/conn/v3/gpio" "periph.io/x/conn/v3/gpio/gpioreg" "periph.io/x/host/v3" ) func main() { if _, err := host.Init(); err != nil { log.Fatal(err) } p := gpioreg.ByName("GPIO2") if p == nil { log.Fatal("Failed to find GPIO2") } if err := p.In(gpio.PullDown, gpio.FallingEdge); err != nil { log.Fatal(err) } for { counter := 0 p.WaitForEdge(-1) countLoop: for { switch p.Read() { case gpio.Low: counter++ if counter >= 200 { fmt.Printf("shutdown start...\n") if err := exec.Command("shutdown", "-h", "now").Run(); err != nil { log.Fatal(err) } } default: break countLoop } time.Sleep(10 * time.Millisecond) } } } プログラムを起動後、2秒以上スイッチを長押しするとシャットダウン処理が始まります 自動起動 ラズパイ起動時に自動でプログラムを起動させるため、systemdのサービスとして登録します /etc/systemd/system/gpio-shutdown.serviceファイルを作成します /etc/systemd/system/gpio-shutdown.service [Unit] Description = hardware shutdown daemon [Service] ExecStart=/opt/gpio-shutdown Restart=always Type=simple [Install] WantedBy=multi-user.target /opt/gpio-shutdownはコードをビルドして生成されたバイナリファイルです。手動でコピーして配置しておきます ファイルが用意できたらサービスを起動します sudo systemctl start gpio-shutdown.service sudo systemctl enable gpio-shutdown.service サービスが正常に起動されたかを確認します sudo systemctl status gpio-shutdown.service Activeの項目がactive(running)であれば準備完了です。ラズパイを起動後、2秒以上スイッチを長押しするとシャットダウン開始します 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む