nilrepresents a zero value in Golang.- hard-coded
nil(interface) is always(type=nil,value=nil) - do not return concreate error types
An interface contains both the type and the value of the underlying concrete struct that it represents.
┌─────────────────────────────────────┐
│ Interface │
│ ┌───────────────┬───────────────┐ │
│ │ Type │ Value │ │
└──┴───────────────┴───────────────┴──┘
func analyzeInterface(i interface{}) {
fmt.Printf("Interface type: %T\n", i)
fmt.Printf("Interface value: %v\n", i)
fmt.Printf("Interface is nil: %t\n", i == nil)
}
var t *A
analyzeInterface(t)
// Interface type: *A
// Interface value: <nil>
// Interface is nil: falsebecause nil ((type=nil,value=nil) ) has different type with (type=*A, value=nil)
var p *int // (type=*int,value=nil)
var i interface{} // (type=nil,value=nil)
if i == nil { // (type=nil,value=nil) == (type=nil,value=nil)
fmt.Println("is nil")
}
i = p // assign p to i
// a hardcoded nil is always nil,nil (type,value)
if i != nil { // (type=*int,value=nil) != (type=nil,value=nil)
fmt.Println("not a nil")
}
// output:
// is nil
// not a nilimport (
"reflect"
"unsafe"
)
// 1) will panic on input struct value
// reflect: call of reflect.Value.IsNil on struct Value
func isNil1(i interface{}) bool{
return i == nil || reflect.ValueOf(i).IsNil()
}
func isNil2(i interface{}) bool {
if i == nil {
return true
}
switch reflect.TypeOf(i).Kind() {
// only works for pointer types
case reflect.Ptr, reflect.Map, reflect.Array, reflect.Chan, reflect.Slice:
return reflect.ValueOf(i).IsNil()
}
return false
}prevent this bad practice
func readFile() error {
var err *fs.PathError
fmt.Println(err == nil) // true
return err
}
func main() {
err := readFile()
print(err == nil) // `false` because it is (type=*fs.PathError, value=nil)
}errortype is an interface- should return
nilinstead ofnil pointer