Go語(yǔ)言中的nil遠(yuǎn)比java中的null要難以理解和掌握。
1.普通的 struct(非指針類型)的對(duì)象不能賦值為 nil,也不能和 nil 進(jìn)行判等(==),即如下代碼,不能判斷 *s == nil(編譯錯(cuò)誤),也不能寫(xiě):var s Student = nil。
s := new(Student) //使用new創(chuàng)建一個(gè) *Student 類型對(duì)象 fmt.Println("s == nil", s == nil) //false //fmt.Println(*s == nil) //編譯錯(cuò)誤:cannot convert nil to type Student fmt.Printf("%T\n", s) //*test.Student fmt.Printf("%T\n", *s) //test.Student<pre name="code" class="plain">
type Student struct{} func (s *Student) speak() { fmt.Println("I am a student.") } type IStudent interface { speak() }
但是struct的指針對(duì)象可以賦值為 nil 或與 nil 進(jìn)行判等。不過(guò)即使 *Student 類型的s3 == nil,依然可以輸出s3的類型:*Student
//var s3 Student = nil //編譯錯(cuò)誤:cannot use nil as type Student in assignment var s3 *Student = nil fmt.Println("s3 == nil", s3 == nil) //true fmt.Printf("%T\n", s3) //*test.Student
2.接口對(duì)象和接口對(duì)象的指針都可以賦值為 nil ,或者與 nil 判等(==)。此處所說(shuō)的接口可以是 interface{},也可以是自定義接口如上述代碼中 IStudent. 使用 new 創(chuàng)建一個(gè) *interface{} 類型的s2之后,該指針對(duì)象s2 !=nil ,但是該指針對(duì)象所指向的內(nèi)容 *s2 == nil
s2 := new(interface{}) fmt.Println("s2 == nil", s2 == nil) //false fmt.Println("*s2 == nil", *s2 == nil) //true fmt.Printf("%T\n", s2) //*interface {} fmt.Printf("%T\n", *s2) //<nil>自定義的接口類似,如下。此時(shí) s4 != nil,但 *s4 == nil ,因此調(diào)用 s4.speak()方法時(shí)會(huì)出現(xiàn)編譯錯(cuò)誤。
var s4 *IStudent = new(IStudent) fmt.Println("s4 == nil", s4 == nil) //false fmt.Println("*s4 == nil", *s4 == nil) //true //s4.speak() //編譯錯(cuò)誤:s4.speak undefined (type *IStudent has no field or method speak)3.將一個(gè)指針對(duì)象賦值為 nil ,然后將該指針對(duì)象賦值給一個(gè)接口(當(dāng)然,該指針類型必須實(shí)現(xiàn)了這個(gè)接口),此時(shí)該接口對(duì)象將不為 nil .
var s5 *Student = nil var s5i IStudent = s5 fmt.Println("s5 == nil", s5 == nil) //true fmt.Println("s5i == nil", s5i == nil) //false