口号
提倡面向接口编程
代码问题抛出
为了返回一个对象给业务调用里面的方法,写了一个NewMySQL函数返回这个对象,大家帮我看看有没有问题
package main
import "fmt"
type Dao interface {
SelectData()
}
type MySQL struct{}
func (m MySQL) SelectData() {
return
}
func NewMySQL() *MySQL {
// 假设一些异常导致返回nil
return nil
}
func main() {
var result Dao = NewMySQL()
if result != nil {
fmt.Printf("值为:%v,类型为:%T", result, result)
} else {
fmt.Println("为nil啊")
}
}
/*
结果为:
值为:<nil>,类型为:*main.MySQL
*/
NewMySQL()不是返回nil吗?为什么result不为nil?
1、首先,nil是什么?
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
官方文档是这样定义的,它是一个零值的占位,他可以表示:pointer, channel, func, interface, map, 或者 slice 类型
2、然后要知道一个东西,interface包含类型和值,只有类型和值都为空时,这个interface才等于nil。只有值为nil,但是类型不为nil时,这个interface是不等于nil的。
问题原理
NewMySQL()内部返回nil,但实际上这份方法定义了返回一个结构体指针,类型是结构体,值是指针,nil只是填充了值,类型依旧是*main.MySQL类型。然后把这个返回值赋给Dao接口,同样的,这个Dao接口类型没有变,只是值为nil。所以在判断是否为nil时,由于类型不为nil,导致判断结果不为nil。
解决方法
NewMySQL方法返回接口类型,而不是结构体或者结构体指针类型
func NewMySQL() Dao {
// 假设一些异常导致返回nil
return nil
}
这样的话nil赋值给接口的时候,这个接口的类型和值都为nil