Open7
Goらしいコード
panicを使わずに、errorをちゃんと返し、エラーチェックを確実に行う
正規表現を避けてstringsパッケージを使う
mapを避ける
メリット
- フィールドと値を関係がわかりやすくなる
- フィールドアクセスに対してエディタに補完が効く
- typoをコンパイル時に検出できる
- メソッドを追加できる
d := map[string]string {
"foo": "bar",
"baz": "qux",
}
type data struct {
foo string
baz string
}
d := data {
foo: "bar",
baz: "qux",
}
mapの用途
気を付けること
mapに対する操作はスレッドセーフでないこと(複数のgorutineから同時にアクセスしたときに変な値を読み込んだり、プログラムがクラッシュしたりする可能性がある)
そのため、mapに対する操作は排他制御に気を付ける必要がある。
その際にはsync.RWMutexを利用して、簡単なオンメモリのkey-valueを実現する
package main
import(
"fmt"
"sync"
)
type KeyValue strcut {
store map[string]string
mu sync.RWMutex
func NewKeyValue(kv *KeyValue) Set(key string) (string, bool) {
kv.mu.RLock()
defer kv.mu.RUnlock()
val, ok := kv.store[key]
return val, ok
}
func main() {
kv := NewKeyValue()
kv.Set("key", "value")
value, ok := kv.Get("key")
if ok {
fmt.Println(value)
}
}
※スレッドセーフとは、マルチスレッド環境において、あるコンピュータプログラムを複数のスレッドで並行して実行しても、問題が生じないように設計された状態や仕様
reflectを避ける
Goはreflectパッケージを用いて、リフレクションを行うことができる
が、基本的に使用しないほうが良い
あまり黒魔術的なことをしてコードが分かりづらくなるよりも、素朴に書くのがGoらしい
巨大なstructを作らず継承させようとしない
Goはstrcutを定義してメソッドを定義するというオブジェクト指向のようなことができる。
しかし、一般的なオブジェクト指向言語における継承を使ったクラスの階層構造のようなことはできない。
継承がない代わりに、埋め込みを使って委譲させることのみができる
「継承より委譲」
言語機能としてそもそも継承を提供しないというGoの割り切り方
考え方として、たくさんのフィールドを持つような巨大なstrcutを定義するのではなく、再利用可能な小さな部品を組み合わせてデータ構造を定義することを心掛ける
※埋め込むとはある構造体のメンバに別の構造体を持つということ
※ 埋め込みは転送、interfaceをメンバにもつ場合は純粋な委譲
並行処理を使いすぎない
レースコンディション(競合状態)のような発見しづらいバグを混入してしまう危険性もある
基本的には直列に書く、ホットスポットで並行処理を活用するのが良い