2022年1月26日

[android] QR Read/Gen

前回つくった Android アプリがようやく承認された。
まあ、数年ぶりだったので、ほぼ新規での審査と同じだったから時間がかかったのだろう。

https://github.com/hirokuma/android-qrcode-genread

 

特にいじったわけでもなく、自分の署名を付けただけです。

QRcode Read/Gen - Google Play のアプリ
https://play.google.com/store/apps/details?id=com.hiro99ma.qrgenread

ボタンが2つある。

  • 1つがクリップボードを読み取ってQRコードにして表示するボタン
  • カメラを起動してQRコードを読み取ってクリップボードにコピーするボタン

 

・・・あ、いま気付いたけど、QRコードを読み取った場合は画像を更新しないので、紛らわしいな。
カメラからスキャンした場合は画像を消してカメラアイコンを表示するようにした。

他の QRリーダと違ってカメラがすぐ起動したり、スキャンした結果からブラウザを立ち上げたりはしないが、シンプルで私が使うには十分だ。

2022年1月22日

[android] QRコードを読み書きしたい

最近 QRコードを扱うことが多い。

GooglePlayで検索するとたくさん出てくるのだが、なんか決め手に欠ける。
勉強がてら作ってみるか。

https://github.com/hirokuma/android-qrcode-genread

 

自分で解析するわけではなく、誰かが作ったライブラリを使う。
ZXing のライブラリが有名なので、それを使うことにした。

ただ、ライブラリ単体だと使うのが面倒そうだったので、 com.journeyapps:zxing-android-embedded を使った。
gradle のここだ。
最初は com.google.zxing を使おうとしたのだけど、android-core と android-integration があって、IntentIntegrator ドキュメントに「別のアプリがいります」と書いてあったのでやめてしまった(書いてあるとおりインストールが求められる)。

 

あとはもう、あちこち見ながら作った。
MainActivity に参照したリンクを書いているので、気になる方はそちらをご参照ください。

持っている Android 端末にいちいち Android Studio を使ってインストールするのが面倒なので Google Play にアップしようとしたのだが、カメラを使うことになるのでプライバシーポリシーがいるのだね......
特に広告も入ってないので、ジェネレータを使わせてもらった。ありがたや。

App Privacy Policy Generator
https://app-privacy-policy-generator.nisrulz.com/

2022年1月16日

[golang][grpc] gRPCサンプル

以前もやったけど、忘れてしまったのでやり直すことにした。

hiro99ma blog: [golang][grpc]protocの準備
https://hiro99ma.blogspot.com/2021/11/golanggrpcprotoc.html

grpc の examples だけやりたいのに全部 clone したくないので、わざわざ fork してリポジトリを作った。
という名目で、README にやることを書き残した。探すのが面倒なのだ。

https://github.com/hirokuma/grpc-go-examples

ちなみに、fork してからブランチやタグを削除するのに以下のサイトが役立った。
ローカルのタグを削除して push --tags とかすれば同期されるのかと思ったけど、そうはいかないようだった。
一度 git tag で全部出して、改行を削除してから push して消した後にローカルを削除した。たぶん一度に格好良くやる方法はあるのだろうけど、まああんまりやる操作じゃないからよかろう。

リモートのタグを一括削除するときは–deleteを使おうと思った話 | WEB EGG
https://blog.leko.jp/post/should-use-delete-option-to-delete-git-branch-or-tag/

gitでブランチやタグを一括削除する - Qiita
https://qiita.com/wagase/items/2248e39460cae2768dd2

そのまま動かす tutorial 1 と、rpc に SayHelloAgain を追加した tutorial 2 を commitしている。
gRPC の Quick start と内容は同じで、ツールのバージョンを上げたり、proto ファイルを更新したりしているだけだ。


greeter_client は flag を使っているので、コマンドライン引数に --name と --addr を指定できるようになっている。
flag は go.mod にも出てこないので golang の標準ライブラリなのだろう。
"--help" と "-h" は何も指定しなかったらヘルプ出力をしてくれた。指定するとエラーにはならずオプションとして使えるようになる。
ショートのオプション名も付けたかったら、たぶん Var 付きの関数を使って複数割り当てるしかないのだろう。

 

便利なのだけど、まだ使いこなせてないなー。

2022年1月10日

[golang] makeはいつ使うのか

プログラミング言語Goを読んでいる。

組み込み関数について説明があまり載っていないようだ。
説明するまでもないのか、章として説明するようなものでもないということなのか。


new と make

C++だと、new はヒープ領域にメモリを確保するものだった。コンストラクタを呼び出したりもしてくれる。
Cだと malloc()系の関数で、これもヒープ領域に確保する。
Javaはnew しかなかったっけか。覚えてない。

Goの場合、メモリを割り当てるという意味では new と make がある。
ただ、これがどうメモリを当てるかというのは new とか make とか、あるいは var とかで決定されるわけではないそうだ。

new

It's a built-in function that allocates memory, but unlike its namesakes in some other languages it does not initialize the memory, it only zeros it.

これが new の説明だ。
初期化はしないけどゼロにはするそうだ。ゼロにするのは初期化とは言わないのか?
ともかく、malloc() して memset()でゼロクリアするようなものだろう。

引数として型だけしか取らないようだ。

make

It creates slices, maps, and channels only, and it returns an initialized (not zeroed) value of type T (not *T).

さて、make は new と違って初期化はするがゼロ埋めするわけではないそうだ。
あるいは、ゼロにするとは限らないという意味だろうか。

 

そもそも、slice 変数を作ったとして、初期値を代入しないのであれば与えたいのは最初に確保しておくメモリサイズくらいしかないだろう。ゼロで埋めておいても特によいことはないと思う。 map もそうだろう。値を追加されてからが勝負(?)だ。 channel もゼロで埋めるんじゃなくて何か特殊なことをしないといけないような気がする。そういうのをひっくるめて「初期化」と呼んでいるんだろう。

そうなると、むしろ new はいつ使うんだろう。構造体か配列くらいか? 構造体も宣言時に代入で初期化できるし、複雑なものであれば New() のようなメソッドを用意する方がよいだろう(たぶんその中でも new は使わないんじゃなかろうか)。
配列のようにサイズが最初から決まっているならゼロでクリアされているというのはありがたい気がする。

 

new も make も使わずに var で宣言しただけの場合はどうなるかというと、その型における「ゼロ値」が代入されるそうだ。構造体であってもそのここの変数は「ゼロ値」で初期化されるのだろう。
「Go には未初期化の変数というものはない」ということなので、どちらかといえば new が異色なのか。でも未初期化にならないと言うことは配列であっても初期化されるはずだから、new はいらないんじゃないの・・・?

例は書いてあるのだけど、どうもピンとこない。
変数名を付けたくないけどメモリだけはほしい、みたいなときに使えるとかも書いてあった。

 

まあ、 new を使いそうになったら「new じゃなくてよいのでは?」と考えるようにしておこう。

2022年1月8日

[golang] vscode と golang の import(2022/01/08)

今の私は、Ubuntu 20.04 で vscode 1.63.2 を使っている。
go のバージョンはこちら。

$ go version
go version go1.17.6 linux/amd64

 

Microsoft の go extension をインストールしているのだが、うまく動いているような動いていないような、よくわからないときがある。
プロジェクトの設定によるような、よらないような。。。

つまり、よくわかってなのだ。


formatOnSave

よくわからんやつの代表格。
設定項目は、"editor.formatOnSave" と、各言語向け設定の中にある "editor.formatOnSave" だけだと思っている。

01: {
02:     "[go]": {
03:         ....
04:         "editor.formatOnSave": false,
05:         ....
06:     },
07:     ....
08:     "editor.formatOnSave": false,
09:     ....

関連項目に "go.formatTool" もあると思う。

で、どちらにも false を指定している(おそらく共通設定の formatOnSave は個別の言語設定に項目があるなら使われないと思う)のだが、保存すると import が埋められてしまうので、設定が効いていないか別の項目が影響しているかだと思う。

Formatting
https://code.visualstudio.com/docs/languages/go#_formatting

特にそういう情報は載っていない。

 

settings.json で「 "go" 」と書いて Tabキーで自動補完?させると、こういう項目があった。

01:     "[go]": {
02:         "editor.codeActionsOnSave": {
03:             "source.organizeImports": true
04:         },
05:     },

これを false にすると、ファイル保存時に import が更新されなくなった。
つまりあれは format しているわけではなく import の整理をしているだけなのだ。

 

ではこの状態で vscode のコマンドで Format Document すると import が更新されるかというと、されない。
そう、 format は整形だけで、 import の整理とは別なのだ。
別のコマンドで「Organize imports」というのがあるので、そちらを実行すると importが整理された。

キーバインドはこうなっていた。設定した記憶がないので、vscode のデフォルトだろう。

01: {
02:   "key": "shift+alt+o",
03:   "command": "editor.action.organizeImports",
04:   "when": "editorTextFocus && !editorReadonly && supportedCodeAction =~ /(\\s|^)source\\.organizeImports\\b/"
05: }

Go言語用というわけでもないと思うのだが、どういうしくみなんだろうね?

 

Format Tool で "goimports" を指定しておくと format時に importも整理されていたのだが、最近はLanguage Serverなるものを使うのがデフォルト設定になっていて、その場合は Format Tool の設定は無視されるらしい。
「Use Language Server」を false にすると Format Document 時に importが整理された。

import を自動で更新してくれると便利でよいのだが、勝手にソースファイルが変更されるのが嫌なときもあるのだ。単純に「勝手に変わるのは気持ち悪い」というだけかもしれんが、まあそういうものだ。


あとは、文字色だけ付けるモードがあるとありがたい。
import が足りないとかそういうのはチェックせず、単に予約語などに色を付けるだけのモードだ。保存するたびに CPU負荷が上がるところを見ると、簡易的なコンパイルなり何なりを実行しているのだと思うけど、私の場合はそういうのいらないからさっさと動いてくれ、ということが多いのだ。

 

Microsoft の Extension を外して、 "Go Custom Format" で goimports などを指定すればだいたいよさそうな気がする(Format Document、ではなく extensionのコマンドで format することになるが)。
色を付けるのは vscode の設定だけでよさそう。もしかしたら今まで golang で使った設定が残っているだけかもしれんけど。

そんなに毛嫌いしなくても良いと思うのだが、Save して数秒間チェックしてから保存されたりすると、何もしないでいいから保存を先にしてくれ~といいたくなってしまうのだ。

 

あまり難しく考えず、遅いときだけ Extension を disable にしておく、でもよいのかもしれんし、Language Server を使わなくしただけで軽くなったような気がしなくもない。 gopls がないと起動するときに怒られるが、インストールしておくと使われてしまいそうなので、同じ名前の空のファイルを作って実行権限でも与えておくと良いだろう。そこまで毛嫌いしなくてもよいとは思うが。

[golang]結局「プログラミング言語Go」を買った

前回、買うかどうかくよくよしていたが、買った。紙の方。

プログラミング言語Go - 丸善出版 理工・医学・人文社会科学の専門書出版社
https://www.maruzen-publishing.co.jp/item/b304432.html

ネイティブのバイナリを作るし、もう少し慣れれば私の C言語以外の主要言語に格上げされることだろう。

 

私にとってこの本の良いところは、だいたいのところをカバーしていそうなところ(まだ読み切ってないので)と、プログラミング言語を扱ったことがある人向けというところだ。初学者向けだと、わかりやすく説明しているだけなのか言語仕様なのか判断できないことがあるからだ。あとは読んでいて「そういうのは分かってるから中身だけ書いてくれ」と思ってしまいそうだからというのもある。

電子書籍にするかどうかは少し迷ったところである。
紙媒体にしたのは、私が電子書籍だと読まないからだ。

この本として気をつけることは、go のバージョンが v1.5 になっていることだろう。
新しくなった部分は自分で取り込むしかない。


こうやって情報がまとまっていて助かるところは、調べようともしなかった情報に気付くことだと思う。

たとえば「ルーン(rune)」なんてものは存在すら知らなかった。%c なんだから文字コードだろう、などと決めつけてはいかんということだろう。
C言語だと「文字列」というのは「\0で終わるデータ」くらいのイメージしかないので、なんかこう Unicode とかそういうのはライブラリにお任せするのだが(そもそも私は文字列をあまり扱わないのだけど...)、言語仕様に入ってるなら知っておかないといかんよね。

 

しかし、それは目を通さないと情報に気付かないということでもある。
この本は約400ページくらいあり、絵や図はそこまで多くないし、コードもそこまでないので、つまり情報量がかなり多い本になる。密度が濃いといえばよいか。

なので、読むのにも時間かかるし、負担が結構かかりそうだ。
ああ若いときに読みたかったわ。。。

2021年12月20日

golangの本を買いにいったが止めた

golang をネットで場当たり的に調べるのも良いが、本を買ってじっくり学ぶというのもやりたい。
私はまだ技術書をデジタル書籍ではうまく扱えないので、本屋さんに行ってきた。

紀伊國屋と丸善を回ったのだが、どちらも同じような状況だった。
買わずに家に帰って調べたのだが(買いに行く前にやれってね)、本屋さんにあったような本しかなかった。

 

入門書でも良いのだけど、インストールの仕方とかツールの使い方とかに比重が置かれているタイプではなく、サーバプログラミングに重点を置いているようなものでもなく、言語仕様に重点が置かれている本が買いたかったのだ。

となると、これしか出てこない。

プログラミング言語Go - 丸善出版 理工・医学・人文社会科学の専門書出版社
https://www.maruzen-publishing.co.jp/item/?book_no=295039

本屋さんにもあったのに買い控えたのは、これが2016年出版と5年前だからだ。オリジナルは2015年。
電子書籍版も2021年5月に出ているのだが、内容が更新されたわけではないだろう。
C言語だと多少古くてもなんとかなると思うのだが、Go言語は最近の言語。
6, 7年も前だと変更がいろいろ行われていそうで止めたのだ。

候補になりそうなのはオライリーさんのだけど、これはまだ日本語になってない。

Learning Go [Book]
https://www.oreilly.com/library/view/learning-go/9781492077206/

というわけで、買うのを止めたのだった。


しかし家に帰ってよく考えたのだが、ツールの使い勝手が変わっても言語自体は変わってないのかも・・・?
そこを調べておくべきだろう。

  • v1.1
    • integer division by zero
    • surrogates in Unicode literals
    • method values
    • return requirements
  • v1.2
    • use of nil
    • three-index slices
  • v1.3
    • 無しなのかな?
  • v1.4
    • for-range loops
    • method calls on **T
  • v1.5
    • map literals
  • v1.6
    • 無し
  • v1.7
    • terminating statements
  • v1.8
    • explicit converting
  • v1.9
    • type aliases
    • 浮動小数点演算の丸め関係
  • v1.10
    • 一応無し
  • v1.11
    • 無し
  • v1.12
    • 無し
  • v1.13
    • リテラルのプレフィクス追加(0b, 0o など)
    • ビットシフト量を unsigned に変更
  • v1.14
    • overlapping interfaces proposal
  • v1.15
    • 無し
  • v1.16
    • 無し
  • v1.17
    • conversions from slice to array pointer
    • unsafe.Add()
    • unsafe.Slice()
  • v1.18
    • これを書いている時点では未定
    • 404 は "to, err := human()" なのね

あまり読まずに抜き出したので、間違いがあったら済まぬ。

 

 

オリジナル本の "The Go Programming Lanuguage" は、どうも v1.5 の時代に書かれているようだ(Contents の PDFより)。

v1.6 以降で気になる変更点は、type alias のサポートとか interface関係かなぁ。
しかし標準ライブラリへの変更や追加もあるだろうから、やっぱり悩むな。。。

2021年12月19日

[golang]go.mod の require にリリースバージョンを付けたい

以前、go.mod で特定の commit-id を指定するやり方を調べた。

hiro99ma blog: [golang] go.mod の pseudo-version
https://hiro99ma.blogspot.com/2021/12/golang-gomod-pseudo-version.html

が、よく考えれば普通は pseudo じゃないバージョンを使っているのだ。
そのバージョンの指定方法を調べておくべきだろう。

https://go.dev/doc/modules/gomod-ref#require

require の文法は

require module-path module-version

で、リリースバージョンか pseudoバージョンとのこと。

リリースバージョンってなんじゃ?
git tag でよいのか?

前回の gogo-test4 に v0.1.0 のタグを付けて push。
GitHub のリリースにはしていないが、tags には出てくる。

https://github.com/hirokuma/gogo-test4/tags

で、これを require している gogo-test3 で指定する。

https://github.com/hirokuma/gogo-test3/blob/66a97f39163f91ab9bd945a1c45ff80de37a6d7d/go.mod#L5

go mod tidy してもエラーにならないから、これでよいようだ。

ただ、git tag って push した後でも消したり差し替えたりできると思うので安心しきってはいかんのかもしれんな。

[golang]ライブラリが持つグローバル変数

グローバル変数と呼んでよいのかどうかわからんが、パッケージ内に変数を置けばグローバル変数みたいな扱いができると思う。
小文字だとパッケージ外からはアクセスできないが、ローカル変数かグローバル変数かでいえばグローバル変数だからどこからアクセスしても本体は同じだ。

 

さて、ではこれがライブラリだったらどういう扱いになるのだろうか?
もし1箇所でしか使っていないなら気にしなくてよいと思うが、複数のパッケージで同じライブラリを import していたら、それは別のメモリとして扱われるのか、同じメモリとして扱われるのか。

https://github.com/hirokuma/gogo-test3

https://github.com/hirokuma/gogo-test4

gogo-test3 の中にパッケージ gogo1 と gogo2 があって、それぞれグローバル変数(パッケージ変数、の方が良いのか?)を置いている。
そしてそれぞれが gogo-test4 を import している。

gogo-test4 はグローバル変数がある。

gogo-test3 の main() で、gogo1 の中で gogo1 と gogo-test4 を更新 → gogo2 の中で gogo2 と gogo-test4 を更新 → gogo1 側の gogo-test4 の値を見てみる、ということをやっている。
結果はこうなる。 2つ数値が出力されるうち、前者が package 内のグローバル変数、後者が gogo-test4 のグローバル変数である。

$ go run .
gogo1 10, 10
gogo2 20, 20
gogo1 10, 20

gogo2 で設定した gogo-test4 の値が gogo1 の方でも取得されているので、取りあえずこういうシンプルな書き方であれば import を複数の箇所で行っていても 1つのものだと判定されるようだ。
New 関数を package が持っていることが多いのは、動的に変数を用意しないと知らないところからアクセスされて値が書き換わっていた、なんてことが起きてしまうのを防ぐためだ。
あるいは、どこからアクセスしても同じデータを使いたいなら、あえてそう作ればよいということだ。

2021年12月5日

[golang] go.mod の pseudo-version

hiro99ma blog: [golang] go.mod の pseudo-version の調べ方がわからん
https://hiro99ma.blogspot.com/2021/11/golang-gomod-pseudo-version.html

git log を加工したらよいのではなかろうか、ということでこうなった。

TZ=UTC git log -n1 --abbrev-commit --abbrev=12 --date=format-local:%Y%m%d%H%M%S

 

たとえばここだとこうなる。

$ TZ=UTC git log -n1  --abbrev-commit --abbrev=12 --date=format-local:%Y%m%d%H%M%S
commit 382e4677bbfb (HEAD -> main, tag: v3, origin/main, origin/HEAD)
Author: hirokuma <hiro9ma@gmail.com>
Date:   20211121014212

    v3

最初は時間がJSTになってて、go mod tidyするとタイムスタンプが違うといわれてしまった。
かといってどうやって UTC にするんじゃ?ってなって。TZ 設定したけど --date=format: にしていたので反映されずに悩んでしまった。

metadata - Git: show dates in UTC - Stack Overflow
https://stackoverflow.com/questions/21363187/git-show-dates-in-utc

 

先頭の 1つだけしか出力しないのだが、私の使い方だとそれで十分だ。

が、ちょっと欲が出るよね?
もうちょっと go.mod 風の出力にならんだろうかと。

$ TZ=UTC git log -n1  --abbrev-commit --abbrev=12 --date=format-local:%Y%m%d%H%M%S --format=format:%ad-%h
20211121014212-382e4677bbfb

コマンドラインが長いのだけど、どうせ記憶できる長さじゃないので alias にでも設定しておけばいいや。