前回
文字列を for-range で回す際に、
繰り返しの要素(1文字1文字)が string
型として現れることを期待していたのですが、
なんと rune
型という気味の悪い型(元ネタ)が代わりに現れて少々困惑してしまいました。
今回はそんな rune
型の基本的な挙動を確認してみました。
rune
型の入出力
まず大前提として、rune
は int32
のエイリアスであり、
さらに Unicode のコードポイント(10進数表記)に該当するのでした。
rune
型の変数に格納できる値は2種類あります。
-
int32
型の数値 -
rune
リテラル
int32
型の数値
package main
import "fmt"
func main() {
var num int32 = 4649
var r1 rune = 946
var r2 rune = num
fmt.Printf("r1 = %v (%c)\n", r1, r1) // r1 = 946 (β)
fmt.Printf("r2 = %v (%c)\n", r2, r2) // r2 = 4649 (ሩ)
var r3 rune = int(num) // error!
// cannot use int(num) (value of type int) as type rune in variable declaration
}
rune
型の値を %c
で出力すると、該当する Unicode 文字が表れて胸が熱くなりますね。
そして、rune 型の変数に int
の格納は許されないことに注意しましょう。
rune
リテラル
package main
import "fmt"
func main() {
var r rune
r = '🥺'
fmt.Printf("%v (%c)", r, r) // 129402
r = '💃🕺' // error!
// more than one character in rune literal
r = "🥺" // error!
// cannot use "🥺" (untyped string constant) as rune value in assignment
}
rune
リテラルは、文字列リテラルと違って シングルクォート(''
) で囲みます。
囲む対象となれるのは、1文字のUnicode文字 や \
で書き始める文字コードです。
ちなみに文字列リテラルは、ダブルクォート(""
)やバッククォート(``
)で囲んで書きます。
rune
型の演算
さて、 rune
型を用いた演算ですが、以下の2点さえ覚えておけばいいと思います。
- 所詮
int32
である -
rune
リテラルとint
型変数との演算では、rune
リテラルがint
型にキャストされる
package main
import "fmt"
func main() {
var r rune = '🥺'
var num int32 = 1232
result1 := r - num // 所詮 int32 である
fmt.Printf("%v (%c) : %T型\n", result1, result1, result1)
// 128170 (💪) : int32型
result2 := r + 'a' // 所詮 int32 である
fmt.Printf("%v (%c) : %T型\n", result2, result2, result2)
// 129499 (🧛) : int32型
var justIntNum int = 334
result3 := justIntNum + '虎' // rune リテラルの int へのキャスト
fmt.Printf("%v (%c) : %T型\n", result3, result3, result3)
// 34716 (螜) : int型
}
ぴえん(🥺)から 1232 を引くと、筋肉(💪)になります。
これ期末試験に出ますよ^^
ぴえん(🥺)に a を足すと、ドラキュラ(🧛)になります。
これはあまり大事ではありません。
そして役に立つのが、rune
リテラルの int
型へのキャストですね。
例えば、関数の戻り値を int
に縛っている場合、関数の中身の処理を int32
でひたすら行っていくのは煩雑でしんどみがあります。
終わりに
JavaScript や Python などの動的型付け言語に慣れていたのであれば、
Go の静的型付け成分に(ほんのちょっぴり)悩まされることがあるでしょう。
特に rune
型は、Go 言語に特有(??)で、その扱いを直感的に理解しづらいと思います。
そのように感じる方々にとって、この記事が役立つものでありますように🙏