[Go] ポインタを取り扱う記号の紛らわしさ

ポインタを取り扱うコードって難しいですよね。プログラミングを習得する上で一つの鬼門になっているようです。

なぜポインタを取り扱うコードは難しいのか、それは文法の記号の紛らわしさが一因になっていると思います。

ポインタを取り扱うコードを書く時に *& どちらを書けばいいんだっけ?と迷ったことはありませんか?私はいつも迷います。

なぜ *& のどちらかを書くかで迷うのか

Go のコード例を示しつつ、理由を考察してみます。

以下の text は string 型の変数で、textRef は string のポインタ型の変数を表します。

var text string
var textRef *string

これらの変数に代入をしてみましょう。

// まずは普通に代入
text = "コーヒー"

// & を付けることで text を指し示すポインタとして代入する
textRef = &text

次にこれらの変数を使う時のことを考えてみます。
fmt.Println() で各変数の値を出力してみます。

// 出力: コーヒー
fmt.Println(text)

// 出力: 0xc000010230 (変数 text を指し示すアドレス)
fmt.Println(textRef)

// 出力: コーヒー (* を付けることで上のアドレスが指し示す先の値を得られる)
fmt.Printf(*textRef)

Go のポインタの基本文法は以上です。
ポインタを取り扱うための記号は基本的に &* の二つだけです。

二つの記号の意味を整理します。

* (アスタリスク) & (アンパサンド)
型を記述する時 型名の前に * を付けることでポインタ型を表す
変数を参照する時 変数名の前に * を付けることでポインタの先の値を表す 変数名の前に & を付けることでその変数のポインタを表す

同じ記号でも使う場面によって意味が異なる点に気がつくと思います。

string をポインタ型にしたいと思ったときに型名の先頭に * につける一方で、
ポインタ変数を string にしたいと思ったときも変数名の先頭に * を付けるのです。

感覚的な話になりますが * は使う場面によって正反対の意味を持つ印象を受けると思います。

私は未だにこれで取り違えることがありますが、なぜ紛らわしいのか認識できているだけでも楽になると思ったので言語化してみました。

理解しやすい記号の覚え方があるといいなと思っていますが、未だに答えが出ていません。(gopls などの Language Server を使ってコーディングしていれば、間違った時に怒られてすぐ気がつけるので大きな支障はありませんが…。)

電子書籍リーダーの使い勝手を左右する「画面消灯までの時間」

電子書籍のリーダーアプリで地味に使い勝手を左右する点が「アプリを無操作で放置したときに画面消灯するまでの時間」だと思っています。

読んでる最中で画面消灯してまた点け直すというのを何度も行うのはちょっとしたストレスです。

消灯までの時間を意図的に制御しているアプリもあるようなので検証して比較してみます。

iOS の画面消灯までの時間の仕組み

iOS では OS 側の設定として画面消灯までの時間を設定できます(設定アプリ => 画面表示と明るさ => 自動ロック から設定可能)。

この時間は 30秒 〜 5分 の範囲で設定可能です。これを長くすれば読書中の消灯は回避できますが、低電力モードが ON になっている間は問答無用で30秒の設定になります。

このこともあって30秒設定の状態で読書するという状況はよくあるのですが、このときの挙動としては20秒経過でバックライトが消灯、30秒経過で完全に画面が消灯となります。

つまり20秒以内に1画面を読み切ってページ送りをすれば画面消灯から逃げ切れます。ゆっくり読んでるとハラハラしますね。

これは OS 標準の挙動であり、アプリ側で消灯時間を制御することもできるようです。実際に各社の電子書籍リーダーアプリを検証してみると違いがありました(比較結果は以下)。

検証時の環境、前提条件

  • 端末: iPhone
  • OS: iOS 14.5.1
  • 各アプリのバージョン: 2021/05/23時点の最新版
  • OS側の消灯時間の設定: 30秒 (低電力モード)

検証結果

Kindle (Amazon)

Kindle は OS 側の設定によらず以下の結果となりました。

  • 5分30秒でバックライト消灯
  • 5分40秒で完全消灯

楽天Kobo (楽天)

楽天Kobo は特に制御されておらず、OS 標準の動作のままでした。

  • 20秒でバックライト消灯
  • 30秒で完全消灯

honto (大日本印刷)

honto も特に制御されていませんでした。

  • 20秒でバックライト消灯
  • 30秒で完全消灯

Doly (ヨドバシカメラ)

Doly も特に制御されていませんでした。

  • 20秒でバックライト消灯
  • 30秒で完全消灯

まとめ

2021/05/23 現在では Kindle だけが画面消灯を抑止する制御が加えられてました。今回検証しなかった他社のアプリがどうかは分かりませんが、今回の結果を見るに制御されている方が珍しいのかなという感じです。

Kindle を使う理由が一つ増えました。他社も真似してほしい!

Mac でスクリプトからの通知が表示されない場合の確認事項

macOS は Mavericks から AppleScript を使ってコマンドラインから簡単に通知を表示させることが出来るようになりました。

# メッセージのみを通知する例
echo 'display notification "通知メッセージ"' | osascript

# メッセージとタイトルを通知する例
echo 'display notification "メッセージ" with title "タイトル"' | osascript

ターミナルからこのコマンドを打つだけで通知センターに通知が表示されます。
設定によっては通知パネルやバナーを表示させることもできます。

しかし、設定によっては上記で通知が表示されない場合があります。
表示されない場合は以下のあたりを疑ってみるといいかもしれません。

その1: スクリプトエディタからの通知を許可しない設定になっている

地味に気をつける必要がある点として osascript コマンドから送信する通知はスクリプトエディタからの通知という扱いになります。
そのためスクリプトエディタの通知を許可しない設定になっていると通知は表示されません。

macOS 通知設定

その2: おやすみモードが ON になっている

夜だけ通知されないといった場合は多分これ。
通知センターのおやすみモードが ON になっていると通知は表示されません。

macOS 通知センター

参考