Golangの文法を自分用メモとしてまとめる。
雑多なメモ
# ライブラリのdocの確認
$ godoc fmt Println
$ godoc os/user Current
# コマンドラインでフォーマット形成
$ gofmt -w file.go
# ドキュメントをローカルポートから見る
$ godoc -http=:6060
// %ホニャララのPrintf (Printlnだとダメ)
fmt.Printf("%T", var) // 変数の型
fmt.Printf("%v", var) // value in default format
fmt.Printf("%d", var) // 10進数で表示
// intは環境によって32bitか64bit,指定したい場合にはint32, int64を使う。
// 文字列からn番目の要素を取り出す
fmt.Println("Hello"[0]) // 72(ASCIIコード)
fmt.Println(string("Hello"[0])) // "H"(stringに戻す)
// エラーを生じうる型変換
i, err := strconv.AtoI("15")
// バイト配列
b := []byte{72, 73} // [72 73]
c := []byte("HI") // [72 73]
string(b) // "HI"
// 可変長引数を関数に渡す
func foo(params ...int){処理} // paramsにはintのスライスが入る
// スライスを展開し各を引数として関数に放る
foo([]int{1, 2, 3}...)
// 標準パッケージのtesting
$ go test ./...
クロージャ(関数閉包)
closureの定義のちゃんとした説明には踏み込まず、具体例からやんわりまとめる。
func incrementGenerator() (func() init) {
x := 0
return func() int {
x++
return x
}
}
func main() {
counter := incrementGenerator()
fmt.Println(counter())
fmt.Println(counter())
}
以上の例だと、counterという変数には無名関数が保存されており、この関数内から、この関数外で定義された変数xを参照している。このため、このxの値は保持され、二度目にcounter()を呼び出した際には、x=1が入っている。
logライブラリ
log.Println("error message")
log.Fatalln("error message") // プログラム終了する
ログをファイルに書き出すようにsettingをするには以下。
func LoggingSettings(logFile string) {
logfile, _ := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
//multiWriterは複数のio.Writerを受け取り、すべてに同時に書き込み対象に設定
multiLogFile := io.MultiWriter(os.Stdout, logfile)
log.SetFlags(log.LDate | log.Ltime | log.Llongfile)
log.SetOutput(miltiLogFile)
}
func main() {
LoggingSettings("test.log")
}
panicとrecover
golangでは使用が推奨されておらず、エラーハンドリングを使うべし。deferで指定する関数に入れることで生じたpanicをキャッチして処理できる。
// panicのキャッチかつプリント
s := recover()
fmt.Println("OK?")
ポインタ周り
// *int型を返す [ポインタ!!]
new(int)
// ポインタではなくスライス型を返す
make([]int, 0)
-
初期化
- スライスやマップは
[]int{}
よりmake([]int, 0)
で初期化が推奨される。 - 構造体は
new(MyStruct)
より&MyStruct{}
で初期化されることが多い。
- スライスやマップは
(構造体のポインタ).(属性値) = (*構造体のポインタ=実態).(属性値)
が成立、つまり、
// 構造体の初期化かつそのポインタの取得
s := &MyStruct{初期化}
// どっちでもいい
s.field1 = "field1"
*s.field2 = "field2"
構造体周り
- 構造体のコンストラクタのプラクティス
func New(x, y int) *Mystruct{
return MyStruct{x, y}
}
- 構造体の破壊的/非破壊的メソッド
// 破壊的メソッドの定義
func (s *MyStruct) overwrite {
s.var = "new value"
}
// 非破壊的メソッドの定義
func (s MyStruct) overwrite {
s.var = "new value"
}
- golangの構造体は継承を
embedding(実現)
によって実現する - non-struct型のメソッドを拡張
// カスタムの新しい型を作る
type MyInt int
func (i MyInt) newMethod {処理}
Type Assertionとswitch-assert文
- Type Assertion
インターフェイスから他の型へはtype assertion
、ある型から他の型へはキャスト
、,type conversion
と呼ぶ。
// interface{}型からint型へ
var a interface{} = 5
b := a.(int) // エラー時にはpanicが生じる
- switch-assert文
switch t := i.(type) {
case int:
処理
case string
処理
default:
処理
}
}