副作用よりも結果を返す純粋関数を優先する
Contents
Prefer pure functions that return results rather than causing side effects. Use pointers only when necessary (e.g., large slices or shared transactions). (副作用を起こすのではなく、結果を返す純粋関数を優先する。ポインタは必要な場合のみ使用する(例:大きなスライスや共有トランザクション))
解説
純粋関数は、同じ入力に対して常に同じ出力を返し、外部状態を変更しません。これにより、関数の振る舞いが予測可能になり、テストが容易になります。副作用を持つ関数は、呼び出し順序や状態に依存するため、デバッグが困難です。ポインタを多用すると、意図しない状態変更が発生しやすくなるため、必要な場合のみ使用すべきです。純粋関数は並行処理でも安全です。
具体例
// 悪い例(副作用を持つ関数)
var globalCounter int
func ProcessItem(item *Item) {
item.Price *= 1.1 // 引数を直接変更(副作用)
globalCounter++ // グローバル状態を変更(副作用)
}
func CalculateTotal(items []*Item) float64 {
total := 0.0
for _, item := range items {
ProcessItem(item) // 元のデータが変更される
total += item.Price
}
return total
}
// 良い例(純粋関数)
func ApplyTax(price float64) float64 {
return price * 1.1 // 新しい値を返す
}
func CalculateTaxedPrice(item Item) Item {
// 元のitemを変更せず、新しいItemを返す
return Item{
Name: item.Name,
Price: ApplyTax(item.Price),
}
}
func CalculateTotal(items []Item) float64 {
total := 0.0
for _, item := range items {
taxedPrice := ApplyTax(item.Price)
total += taxedPrice
// 元のitemsは変更されない
}
return total
}
// ポインタが必要な例(大きなデータ構造の効率的な処理)
type LargeDataSet struct {
Data []byte // 数MBのデータ
}
func ProcessLargeData(data *LargeDataSet) error {
// 大きなデータのコピーを避けるためポインタを使用
return processBatch(data.Data)
}
// トランザクション内での共有が必要な例
func UpdateWithTransaction(tx *sql.Tx, user User) error {
// トランザクションは共有する必要がある
return tx.Exec("UPDATE users SET name = ?", user.Name)
}
参考リンク
副作用よりも結果を返す純粋関数を優先する https://www.tricrow.com/core/coding-standard/pure-functions.html

