Go言語では、変数に初期値を割り当てずに宣言すると、その型のゼロ値が自動的に割り当てられます。この機能は、プログラムのバグを減らし、初期化の手間を省くことに役立ちます。
基本型のゼロ値
- 整数型(int, int8, int16, int32, int64 など): ゼロ値は 0 です。
- 浮動小数点型(float32, float64): ゼロ値は 0.0 です。
- 論理型(bool): ゼロ値は false です。
- 文字列型(string): ゼロ値は空文字列 "" です。
複合型のゼロ値
- ポインタ: ゼロ値は nil です。これは、何も指していないことを意味します。
- スライス: ゼロ値も nil です。長さと容量がともに0のスライスを表します。
- マップ: ゼロ値は nil で、キーと値のペアが存在しないことを意味します。
- チャネル: ゼロ値は nil で、初期化されていないチャネルを表します。
- インターフェース: ゼロ値は nil で、どの具体的な値も保持していないことを意味します。
- 構造体(struct): 各フィールドがその型のゼロ値を持つ状態です。
ゼロ値の利用例
ゼロ値の概念は、Go言語のプログラムでエラーを防ぐために役立ちます。例えば、マップに値を追加する前に初期化を忘れていた場合、プログラムはパニックを起こす代わりに、nil マップを操作しようとして静かに失敗します。しかし、この振る舞いを適切に扱うことが重要です。
package main
import "fmt"
func main() {
var s string // ゼロ値は ""
fmt.Println(s) // 出力: ""
var i int // ゼロ値は 0
fmt.Println(i) // 出力: 0
var p *int // ゼロ値は nil
fmt.Println(p) // 出力: <nil>
var myMap map[string]int // ゼロ値は nil
// myMap["one"] = 1 // この行はパニックを引き起こす可能性があります。
// マップを使用する前に初期化が必要です。
myMap = make(map[string]int)
myMap["one"] = 1
fmt.Println(myMap) // 出力: map[one:1]
}
ゼロ値は、関数が期待した型の値を返さない場合にも役立ちます。例えば、エラーが発生した場合、関数はその型のゼロ値を返すことがよくあります。
ゼロ値練習
下記のコードに、if val, ok := m[key]; ok {...}else{...}
の意味は何でしょうか?
package main
import "fmt"
func main() {
m := map[string]int{"one": 1, "two": 2}
if val, ok := m["two"]; ok {
fmt.Println("値:", val) // キーが存在する場合、値を出力
} else {
fmt.Println("キーが存在しません。")
}
if val, ok := m["three"]; ok {
fmt.Println("値:", val)
} else {
fmt.Println("キーが存在しません。") // キーが存在しない場合の出力
}
}
if val, ok := m[key]; ok {...}
という構文は、マップ(map)から特定のキーに対応する値を安全に取得するためによく使用されます。この構文は、マップから値を取得し、そのキーが存在するかどうかを同時にチェックします。
- m[key]は、マップmからキーkeyに対応する値を取得します。
- val, ok := m[key]は、2つの値を返します。
- valは、キーに対応する値です(キーが存在する場合)。キーが存在しない場合、valはその型のゼロ値になります(例えば、intの場合は0、stringの場合は""など)。
- okは、bool型で、キーがマップに存在する場合はtrue、存在しない場合はfalseを返します。
- ifステートメントは、okの値をチェックし、true(キーが存在する)の場合はifブロック内のコードを実行し、false(キーが存在しない)の場合はelseブロック内のコードを実行します。
いかかでしょうか?