2023/12/02

最近の go work

"go work" は比較的最近使えるようになった。
というと使いこなしているように見えてしまうが、実は初めて使う。。。

Tutorial: Getting started with multi-module workspaces
https://go.dev/doc/tutorial/workspaces

"go work" の "work" は workspace の work だろう。

このチュートリアルを最後まで行うと、workspace/ の中はこうなっている。赤枠がチュートリアルで作成した部分、それ以外は git clone で持ってきた部分だ。

 

hello.go で "fmt.Println(reverse.String("Hello"), reverse.Int(24601))

の reverse.Int(24601) はオリジナルの "golang.org/x/example/hello/reverse" にはなく、今回追加した int.go で実装されている。従来、こういう場合は go.mod の require にある "golang.org/x/example/hello/reverse" を replace で相対フォルダ指定して「実はこっち使ってます」宣言するのだが、"go work" のしくみを使うとそれが不要になっているというのがポイントだと思っている。

同じような使い方をするなら、誰かのリポジトリを GitHub fork して自前でちょっと変更したバージョンを使いたいとかだろうか。ただ fork すると別リポジトリとして扱いたいので git submodule で "go work" の中に配置するとかがよいのかな?

あるいは、単純に同じリポジトリの中に go.mod を複数持って相手を参照するような場合でも良いのか。gRPCサーバのアプリを作ったとき、protobuf の定義ファイルも同じリポジトリにおいたのだが、proto定義は変わらないのにサーバの更新だけ進むのでなんだかなー、という気持ちになっていた。
そういう場合にうまいこと使えないだろうかと考えたが、クライアントアプリも同じリポジトリで運用するならよさそうな気がする。気がするが、それは単に replace を書かなくていいのが便利なだけで gRPC の件とは何の関係もないな。

サーバのリポジトリの中に proto があると、クライアントアプリを作りたいだけなのに go.mod にサーバのパッケージを書くのでいらないものまでダウンロードすることになるというのがなんか嫌でね。どうせサーバもクライアントも同じPCで開発するだろうからいいやん、と言われればそれまでなのだが。

 

"workspace" という名前の通り、同じワークスペースにある go.mod はネットワーク参照ではなくローカル参照してくれるのが便利、という考え方で良いのかな。試作している間、repalce でローカルを読むように変更する手間が面倒だったので、workspace 自体は git 管理せずに作業中だけ使うというやり方でよいかもしれん。


最近の go get

"go get" の仕様が変わったという話は聞いていたし、実際に違いも感じるのだが、「なんとなく」で go get したり go mod tidy したりしている。
そのせいだと思うが、git clone してビルドするだけなのに go.mod が更新されていたり go.sum が更新されたりして落ち着かない。
それに過去の仕様を覚えているというわけでもない。

あきらめて、いまの go v1.21 くらいだとどう使うのが普通なのか調べておこう。


なるべく go.dev から参照していきたい。解説記事を読んだとしても、私が過去の仕様を知らないので「これは古い内容だ」という判断ができないのだ。

まず、go v1.17 から "go get" で実行ファイルのインストールが行われなくなった。
その代わりに "go install" を使いなさいということだ。

Deprecation of 'go get' for installing executables - The Go Programming Language
https://go.dev/doc/go-get-install-deprecation

その代わり "go get" がどうなったかというと、go v1.18 から go.mod への追加、更新、削除を行うようになったということだ。


今の "go get" の説明はここにあった。

go command - cmd/go - Go Packages
https://pkg.go.dev/cmd/go#hdr-Add_dependencies_to_current_module_and_install_them

"Add dependencies to current module and install them" というタイトルだったが、実際は更新や削除までやるようだ。
コマンド単体の説明があったので、こちらの方がよいか。

go get
https://go.dev/ref/mod#go-get

  • Upgrade a specific module.
  • Upgrade modules that provide packages imported by packages in the main module.
  • Upgrade or downgrade to a specific version of a module.
  • Update to the commit on the module's master branch.
  • Remove a dependency on a module and downgrade modules that require it to versions that don't require it.
  • Upgrade the minimum required Go version for the main module.
  • Upgrade the suggested Go toolchain, leaving the minimum Go version alone.
  • Upgrade to the latest patch release of the suggested Go toolchain.

多い、多いよ。。。

勝手に分類するなら、個別パッケージ向けかメインモジュール向けかというところか。

個別パッケージ向け

# Upgrade a specific module.
$ go get golang.org/x/net

# Upgrade or downgrade to a specific version of a module.
$ go get golang.org/x/text@v0.3.2

# Update to the commit on the module's master branch.
$ go get golang.org/x/text@master

# Remove a dependency on a module and downgrade modules that require it
# to versions that don't require it.
$ go get golang.org/x/text@none

# Upgrade to the latest patch release of the suggested Go toolchain.
$ go get toolchain@patch

メインモジュール向け

# Upgrade modules that provide packages imported by packages in the main module.
$ go get -u ./...

# Upgrade the minimum required Go version for the main module.
$ go get go

# Upgrade the suggested Go toolchain, leaving the minimum Go version alone.
$ go get toolchain


メインモジュールというのはカレントディレクトリか親ディレクトリの go.mod を指すそうだ。go.dev のドキュメントは "go get" や "go.mod" のフォントが若干他とは違っているようだけど、そのくらいだと見分けが付けづらいのよねぇ。

昔の "go get -d" が go v1.18 からはデフォルトの挙動になっている。"-d" がない場合はそのパッケージのビルドとインストールまでやっていた挙動がなくなったというのが仕様変更でよく言われている内容ということになる。

ここの用例ではオプションがあるけれども "go get" だけでも動作する。パッケージを指定していないのでメインモジュールに向けての操作になるはず。"-u" がないからアップグレードでもないし indirect な require だけ更新するのだろうか?


ここまで "go get" を見てきたが、パッケージの取得だけなら "go mod tidy" を使うイメージを持っている。が、 "go mod tidy" で go.sum が更新されたことがあるような気がするのだ。
なんとなく "go get" だけ実行したときと同じような感じがする。

go mod tidy
https://go.dev/ref/mod#go-mod-tidy

  • adds any missing module requirements necessary to build the current module’s packages and dependencies
  • removes requirements on modules that don’t provide any relevant packages.
  • It also adds any missing entries to go.sum and removes unnecessary entries.

こちらは go.modとソースコードの関係性を重視しているのか? "go get" は "-u" 指定しない限りは indirect くらいしか更新しないようだが "go mod tidy" は不要なパッケージがあれば indirect でなくても削除していた。ただ新しいバージョンがあっても更新はしないので、ビルドできるかどうかだけ判断しているのかな?

2023/11/25

protoc-gen-go-grpcの-Mオプションがうまくいかない

gRPC の勉強というか仕事というか。

適当に proto ファイルを作って、protoc-gen-go と protoc-gen-go-grpc をインストールした状態で protoc を実行する。
が、エラーになった。

protoc-gen-go-grpc: unable to determine Go import path for "rpc.proto"

Please specify either:
       • a "go_package" option in the .proto source file, or
       • a "M" argument on the command line.

See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.

--go-grpc_out: protoc-gen-go-grpc: Plugin failed with status code 1.

今回は自作した proto ファイルなので好きに編集できるが、別のところが提供している proto ファイルを使う場合は加工したくない。

なので --go_opt=M を付けて protoc を実行すると成功した。

2023/11/19

モダンスタンバイ?

ThinkPad T14s を購入した。
OSは Windows11 Home。

充電をしていない場合、蓋を閉じるなり、電源ボタンを押すなり、Fn+4 を押すなりするとスリープしている。
どうやってスリープしていると判断しているかというと、ThinkPad LED(表紙とパームレストにあるLED)が点滅しているかどうかである。
この LED の説明を探しても見つからないので、たぶんそうだろうという判断である。


充電中の場合、上に書いた操作のどれを行っても ThinkPad LED が変化しない。ファンも回っている。そうなるとスリープしたように見えない。

ただ検索すると、スリープ中もファンが回っているという記事がいくつも見つかるので、実はスリープしているのかもしれない。
そうやって調べていくと、モダンスタンバイという機能が見つかった。

モダン スタンバイ | Microsoft Learn
https://learn.microsoft.com/ja-jp/windows-hardware/design/device-experiences/modern-standby

スマートフォンのように画面が消えてスリープになっているときでもネットワークにつながったままにできるらしい。
充電中だけモダンスタンバイになっている? LEDの点滅はスリープとはあまり関係が無い?いろいろ謎はあるのだが、とりあえず無効にしてみると分かるだろう。

 powercfg /a で S0 低電力アイドルになっていることを確認した。

How to Disable Modern Standby in Windows 11 and Windows 10
https://winaero.com/how-to-disable-modern-standby-in-windows-11-and-windows-10/

レジストリ操作がいるのか。。。
再起動して確認。

あれ? 普通のスリープってのにならないのか?
実際に Fn+4 などで試してみたが休止状態になった。充電中でもそうなったのでモダンスタンバイは無効になったようだ。
設定画面でも電源を切る時間しか項目が出なくなった。

そういえば BIOS ... UEFI の設定にスリープ関係があったような・・・なかった。

 

モダンスタンバイか休止状態の二択しかないのか。

ただ、一度設定を変更したのが良かったのか、充電中でも LED が点滅するスリープになるようになった。


2023/11/18

ThinkPad T14s Gen4

比較的最近、ThinkPad T14sを買いました。Gen4 です。


トラックポイントを使っていますが、メーカーが変わっていました。
Synaptics から ELAN になりました。
だからかどうかわかりませんが、操作感が結構違うように感じます。

以前はしばらく使っていると反動?で自動的にカーソルが動くことがありました。
最初は「なんじゃこりゃ!」と驚いたのですが、慣れてしまうと不思議なことに「元気だねー」くらいの気持ちでいられるようになりました。

今回のトラックポイントですが、そういう動作はしなくなったように思います。
ですが、カーソルが動かなくなることがあるような気がします。「気がします」と弱気なのは、押している力がそのとき弱くなったのかもしれないとちょっとだけ思うからです。指を離して同じくらいの力で(と私は思っている)操作するとまた動きます。
まだ慣れてないですが、これもいつか慣れるのでしょうか。

もう1つ違和感があるのは、同じ方向に力を加えた後に指を離すとカーソルが逆方向にちょっと動くことがあるところです。
カーソルなら気にならないのですが、中央ボタンを押したままでスクロール動作をさせたときは指を離すと逆方向にスクロールしてしまうので気になります。
これはソフトウェアで処理できそうなので、そういう調整ができるとうれしいです。急に逆方向に力が加わったときは多少の移動量は捨てるとか。

トラックポイント関連の設定項目ですが、たぶんこれらになります。
パッドもありますが、私が使っていないので省略します。

  • Windowsの設定画面からできる「マウスポインターの速度」

  •  マウスのプロパティの速度とポインターの精度チェックボックス(上と同じもの?)


  • ELAN TrackPoint for ThinkPadでの感度設定


 

感度の設定でスティックを押す力とカーソルの動き始めが調整できそうです。これを大きくすると弱い力でカーソルが動いてくれそうでした。
ただ、同時に動く移動量も多くなってしまうようで、そちらは速度で調整するようです。難しい・・・。


中央ボタンを押してスクロールさせた場合ですが、どうも Windowsの標準スクロールとは違う経路を通っているような感じがします。
別のソフトウェアでスクロールを調整するアプリがあったのですが、その影響を受けなかったからです。まあ、スクロールはするので違う経路があるだけなのでしょうが。

うまく言えないのですが、Excel などで横スクロールさせると間がすっ飛びます。まあ、縦スクロールもそうなのですが。
別のアプリでは縦スクロールだけ重たかったです。
まあ、これはアプリのせいかもしれませんが、ともかくアプリによって違いが発生することがあるということのようでした。