Go-তে প্রতিটি ভ্যারিয়েবলেরই একটি মান থাকে। কোনো ভ্যারিয়েবল ডিক্লেয়ার করার সময় মান অ্যাসাইন না করলে সেটি তার টাইপের জিরো ভ্যালু হিসেবে সেট হয়ে যায়।
বেসিক টাইপগুলো, যেমন bool, সংখ্যাসূচক টাইপ আর string, প্রতিটিরই একটি নির্দিষ্ট জিরো ভ্যালু থাকে:
| টাইপ | জিরো ভ্যালু |
|---|---|
| bool | false |
| int, int8, int64, etc. | 0 |
| float32, float64 | 0 |
| complex64, complex128 | 0+0i |
| string | "" |
যেসব টাইপ অন্তর্নিহিত ডেটা রেফারেন্স করে, যেমন পয়েন্টার, ফাংশন, ইন্টারফেস, স্লাইস, চ্যানেল আর ম্যাপ, প্রতিটির জিরো ভ্যালু nil।
তবে অ্যারে আর স্ট্রাক্ট কখনোই nil হয় না, কারণ তারা ডেটা সরাসরি ধারণ করে, সেটির রেফারেন্স নয়।
অ্যারের প্রতিটি এলিমেন্ট আর স্ট্রাক্টের প্রতিটি ফিল্ড তার নিজের টাইপের জিরো ভ্যালু দিয়ে ইনিশিয়ালাইজ হয়।
উদাহরণস্বরূপ, var a [3]int লিখলে [0, 0, 0] অ্যারেটি তৈরি হয়।
শুরুর মান ছাড়া var যেকোনো টাইপের জিরো ভ্যালু দেয়:
var myBool bool // false
var mySlice []int // nil
var p Person // Person{Name: "", Age: 0}
স্ট্রাক্টের ক্ষেত্রে কম্পোজিট লিটারাল T{} একটি বিকল্প:
myPerson := Person{} // equivalent to var myPerson Person
new(T) যেকোনো টাইপের জিরো ভ্যালুতে একটি পয়েন্টার রিটার্ন করে।
এটি সাধারণত স্ট্রাক্টের সাথে বেশি ব্যবহৃত হয়, যদিও বেসিক টাইপেও কাজ করে:
p := new(Person) // *Person, pointing to Person{Name: "", Age: 0}
s := new(string) // *string, pointing to ""
i := new(int) // *int, pointing to 0
Go-তে জিরো ভ্যালু একটি স্বাভাবিক ও কাজের শুরুর অবস্থাকে বোঝায়।
একটি bool ডিফল্টভাবে false হয়, যা একটি ফ্ল্যাগ হিসেবে কাজ করতে পারে:
var done bool // action not done yet
done = true // action now done
একটি ইন্টিজার ডিফল্টভাবে 0 হয়, যা একটি কাউন্টার হিসেবে কাজ করতে পারে:
var count int
count++ // 1
count++ // 2
স্ট্রাক্টের ক্ষেত্রে প্রতিটি ফিল্ড তার নিজের টাইপের জিরো ভ্যালু দিয়ে শুরু হয়।
একটি []string ফিল্ডওয়ালা Stack ডিক্লেয়ার করার সময়েই একটি কার্যকর খালি স্ট্যাক হয়ে যায়।
যেহেতু nil স্লাইসে append কল করলে এটি একটি নতুন ব্যাকিং অ্যারে বরাদ্দ করে, তাই কোনো কনস্ট্রাক্টরের দরকার হয় না:
type Stack struct {
items []string
}
func (s *Stack) Push(v string) {
s.items = append(s.items, v)
}
func (s *Stack) IsEmpty() bool {
return len(s.items) == 0
}
var s Stack
fmt.Println(s.IsEmpty()) // true
s.Push("a") // append allocates a new backing array
fmt.Println(s.IsEmpty()) // false
nil জিরো ভ্যালুওয়ালা বেশিরভাগ টাইপ ব্যবহারের আগে ইনিশিয়ালাইজ করা দরকার, নাহলে প্যানিক হয়।
nil স্লাইস হলো ব্যতিক্রম: আপনি এর ওপর রেঞ্জ করতে, এতে অ্যাপেন্ড করতে, আর নিরাপদে এটিকে len ও cap-এ পাস করতে পারেন।
কোনো মান রাখার আগে ম্যাপ ইনিশিয়ালাইজ করা উচিত:
var m map[string]int
m["key"] = 1 // panic
ম্যাপ সাধারণত দুইভাবে ইনিশিয়ালাইজ করা হয়:
m1 := make(map[string]int)
m2 := map[string]int{}
m1["key"] = 1 // ok
m2["key"] = 1 // ok
ব্যবহারের আগে পয়েন্টার nil কি না তা যাচাই করুন:
var p *int
if p == nil {
fmt.Println("no value assigned")
return
}
fmt.Println(*p) // p is not nil
বেসিক টাইপ সবসময় একটি নির্দিষ্ট মান ধারণ করে, তাই এদের nil-এর সাথে তুলনা করা একটি কম্পাইল এরর:
var myString string
if myString == nil {
// compile error: mismatched types
}