1日1個 golang のクイズを出す @DailyGolangQuiz という twitter アカウントを見つけたので既存の質問に答えてみた。
Do you know length of the smile in #golang?
package main
import ."fmt"
func main() { Println(len("😄")) }
— DailyGolangQuiz (@dailygolangquiz) September 21, 2015
golang の string は len でバイト列数が返ります。スマイル絵文字は 4 バイトです。
Why this code prints 1? #golang
package main
import . "fmt"
func main() {
s := 0
for i := range []int{1, 2} { s += i }
Println(s)
}
— DailyGolangQuiz (@dailygolangquiz) September 22, 2015
golang の range-for はバインド変数を1つ取る時はインデックスが返ります(2つの場合は2つ目が実値)。for が2回実行されます。よって 0 + 1 で答えは 1 です。
#golang #quiz Fix code below so it prints first chars.
package main
import."fmt"
func main(){Println("Go home!"[0:1]);Println("🏠🚴"[0:1])}
— DailyGolangQuiz (@dailygolangquiz) September 22, 2015
golang の string は添え字を使うとバイトが、sliceでバイト列が返ります。文字として扱うには rune でキャストする必要があります。
package main
import."fmt"
func main(){Println("Go home!"[0:1]);Println(string(([]rune)("")[0:1]))}
#golang Add one char to print 1:
type T struct { V int }
func (t T) Do() { t.V=1 }
func main() { t := T{}; t.Do(); Println(t.V); }
— DailyGolangQuiz (@dailygolangquiz) September 23, 2015
golang のレシーバはメソッド呼び出し時にコピーされます。Do を呼び出してレシーバ t をそのまま扱うには Do の宣言でレシーバをポインタで宣言する必要があります。アスタリスク1文字だけ足します。
package main
import . "fmt"
type T struct { V int }
func (t *T) Do() { t.V=1 }
func main() { t := T{}; t.Do(); Println(t.V); }
一見リファレンスしていない様に見えますが、実際には C 言語でいう t->V = 1
と同じ働きとなります。
#golang Why does it print "1 false"?
func main() {
switch ok := false
{
case true: Println("1", ok)
case false: Println("0", ok)
}
}
— DailyGolangQuiz (@dailygolangquiz) September 23, 2015
golang の switch は引数を取らない記述が可能です。この場合の switch は評価値を持っていません。実際には以下と同じ意味となります。
package main
import . "fmt"
func main() {
switch ok := false; {
case true:
Println("1", ok)
case false:
Println("0", ok)
}
}
実際に発言のコードを golang playground で Format すると上記のコードに変換されるのが分かるはずです。