golangを動かして思ったことを雑多にメモする
大きくなりそうなものは別途記事としてまとめる
静的解析が便利(らしい)
静的解析とは
コードを実行せずにきれいにしてくれるマン
golang自体がシンプルなコードで、静的解析のしやすさを目指しているらしく
静的解析との相性がいいらしい。
https://golang.org/doc/faq#change_from_c
Second, the language has been designed to be easy to analyze and can be parsed without a symbol table.
fmt
公式から提供されているフォーマッタ。
ファイル保存のタイミングで、自動的にソースのフォーマットを行ってくれる。
実施してくれるのは
- 行間のフォーマット
- 変数、型のインデント揃え
- 不要(ソース内未使用)パッケージの削除
- 制御構文の()削除※
※golangはif,switch,forの制御構文に()は利用しない
fmtやgoのフォーマットに関する詳しい情報はこちら
Command gofmt
Effective Go
使おうと思っている自作のパッケージをimportに書いて、
コード内で使用せずに保存すると消えてしまうのでちょっと悲しい。
lint
コードの改良案を提案してくれる。
おおまかな提案内容は以下の通り
- 構造体へのコメント付与
- パブリック関数へのコメント付与
vet
デッドコードの検出をしてくれる。
デフォルトじゃ入っていない気がする。
未着手。
packageの扱い
とりあえず色々ソースを作って動かそうと思ってこんなディレクトリ構成にしてる。
gogo.go
は疎通確認、person.go
は構造体のテストで
お互い独立したソースファイルである。
golang
├gogo.go
└person.go
goは
- 少なくとも1つの
package
に所属する必要がある - コンパイル→実行時に
package main
のmain
関数を実行する
ので上記両ファイルともpackage mainに所属させ、main関数を作成すると
修飾子が重複していると注意されてしまう。
go run person.go
のようにファイル名を指定して実行すると
一応実行はできるのだが、ちょっと気持ちわるい。
パッケージへの所属が必須の言語ではどう整理するのが正解なのか。
一旦は作りたいソースごとにパッケージにわけ、
main.goでソースを呼び出す形に変更することに。
golang
├main.go
├hello
│└gogo.go
└person
└person.go
package main
import "./person"
import "fmt"
func main() {
fmt.Println("start")
person.score()
}
package person
import (
"fmt"
)
// Person はテストの点数管理の構造体です。
type Person struct {
name string
english int
}
func score() {
bob := Person{"Bob", 60}
fmt.Println(bob.name, bob.english)
if bob.english > 60 {
fmt.Println("OK")
} else {
fmt.Println("NG")
}
}
これでmain.go
から自作のpackage person
を読み込めると思ったのだが、
参照できず、import文から削除される・・・
原因を調査したところ、golangでは
メソッド名が小文字の場合、package外に非公開(private)、
メソッド名が大文字の場合、package外に公開(public)という設定になるらしい。
公式ドキュメントだとこのあたり?
If you have a field called owner (lower case, unexported), the getter method should be called Owner (upper case, exported), not GetOwner. The use of upper-case names for export provides the hook to discriminate the field from the method.
下記の通りメソッド名を大文字にしたところ実行できた。
小文字でも自コード内での参照はできるため、エラーにならず
原因解明に時間がかかった。
package main
import (
"fmt"
"./person"
)
func main() {
fmt.Println("start")
person.Score()
}
package person
import (
"fmt"
)
// Person はテストの点数管理の構造体です。
type Person struct {
name string
english int
}
// Score 評価のためのメソッド
func Score() {
bob := Person{"Bob", 60}
fmt.Println(bob.name, bob.english)
if bob.english > 60 {
fmt.Println("OK")
} else {
fmt.Println("NG")
}
}
go run main.go
start
Bob 60
NG