プログラミング言語 Go を読みながら、気になったことをメモ。
Hello, 世界
最初に驚いたのは、以下のコードがコンパイルエラーになること:
package main
import "fmt"
func main()
{
fmt.Println("Hello, 世界")
}
main()
と {
の間に改行を入れてはいけないのである。(1.1 / p3)
他にも
- 不要な import 宣言があるとコンパイルエラー( 1.1 / p3 )
なんかも驚いた。
地味に心地よいのは、ビルドした結果のファイル名がソースコードのファイル名から取られるところ。 gcc なんかだと 指定しないと a.out
になるのがちょっと不便に感じていたので。
私が windows の cl.exe
に慣れているだけかもしれない。
コマンドライン引数
// コマンドライン引数をそのまま出す
package main
import (
"fmt"
"os"
)
func main() {
var s, sep string
for i := 1; i < len(os.Args); ++i {
s += sep + os.Args[i]
sep = " "
}
fmt.Println(s)
}
がエラーになるのも驚いた。C++ 好きなので、 ++
書くなら前置でしょ、と思ったんだけど、エラーになった。後置しかない。そして、式ではなく文なので値を取れない。( 1.2 / p6 )
なるほど式じゃないなら前置は要らないね。
先程の関数定義の {
と同様、 for
文の {
の直前には改行を入れてはいけない。( 1.2 p6 )というのも意外。固いね。
もっと意外なのは、「使われないローカル変数を許しません」という点。
未使用のローカル変数は軽い警告として黙らせてしまいがちな感じだけど、むしろエラーなのか。
初期化の「:=
」と再代入の「=
」が区別されているのは心地よく感じる。コロン忘れがちだけど。
あと。echo1.go と echo2.go を同じフォルダに作ったら VSCode が文句を言ってきた。ひとつのフォルダに main 関数はひとつだけにしてくれということらしい。そういうものか。
重複した行を見つける
ここで一番驚いたのは、map の順序が実行するたびに異なるという点。実際に実行してみたら本当に毎回異なった。びっくり。
あと、fmt.Printf
の %g
の説明がやや不十分と思ったので、例を書いておこうと思う。
// コマンドライン引数をそのまま出す
package main
import (
"fmt"
)
func test(s string) {
fmt.Printf("%s : "+s+"\n", s, 3.141592653589793238)
fmt.Printf("%s : "+s+"\n\n", s, 3.141592653589793238e10)
}
func main() {
test("%f")
test("%g")
test("%e")
}
を実行すると、
%f : 3.141593
%f : 31415926535.897934
%g : 3.141592653589793
%g : 3.1415926535897934e+10
%e : 3.141593e+00
%e : 3.141593e+10
が出力される。つまり、%f
は、XX.XX 形式。 %e
は、X.XXX+eX 形式。%g
は、桁数を見て、%f
か %e
のどちらかにする。桁数も違うみたいだけど。
ファイルの Close
が陽に呼ばれているけど、C# の using
、Java の try-with-resources、 Python の with 文、C++ の デストラクタ のようなものを使って避ける方法はあるのだろうか。
goルーチンで fetch
ソースコードを見ても、私の中にメンタルモデルを作れなかった。
第8章をしっかり読まなくてはいけないけど、だいぶ先だね。
Webサーバ
シンプルな記述で好ましい。
しかし、mutex の lock/unlock を陽に書かなくてはいけないのが残念。
あるいは避ける方法があるのだろうか。
今日のところはこれぐらいで。
と、書いたけど、2章も読んだ。 see https://qiita.com/Nabetani/items/d053304698dfa3601116