'nil' is surprising NOT a keyword, but a predeclared identifier
nil of different types means completely DIFFERENT thing!!! eg. nil pointer is different from nil interface !!!
map, slice, pointer, interface, channel, func "nil is predeclared identifier representing the zero value for a point, channel, func, interface, map or slice"
nil
- pointer: points to nothing
- channel: points to nothing
- func: points to nothing
- interface: (concrete-type, value) == (nil, nil)
var s fmt.Stringer // Stringer (nil, nil)
fmt.Println(s == nil) //true
var p *Person // nil of concrete type *Person !!
var b fmt.Stringer = p // Stringer (*Person, nil)
fmt.Println(s == nil) // FALSE !!!- map: similar to slice
- slice: slice that doesn't have a backing array, still has len and cap values=0
struct, string, array, numerics, bool
Making nil Useful, we almost could do anything, as long as we don't de-reference nil (*p when p == nil will panic)
var t *foo
foo.Something() // Should not Panic!!!
// Solution:
type person struct{}
func (p *person) sayHi(){fmt.Println("hi")} // works!!!
func (p *person) DoSomething() {
if p == nil {
// anything without painc! eg. return
}
// anything else
}
func (t *tree) Sum() int {
if t == nil {
return 0
}
return t.v + t.l.Sum() + t.r.Sum()
}
func (t *tree) String() string {
if t == nil {
return ""
}
return fmt.Sprint(t.l, t.v, t.r)
}
func (t *tree) Find(v) bool {
if t == nil {
return false
}
return t.v == v || t.l.Find(v) || t.r.Find(v)
}Useful nil!!!!!!!
- pointer: many things CALL METHODS!, as long as we don't de-ref *p
- channel: many things, stop a channel
- func: default func?
- interface: different from nil pointer!
- map: we can do anything READONLY! m[key] works!!
- slice: anything as a zero values, as long as we don't s[index]