Bootstrap

Golang函数返回值少用对象

口号

提倡面向接口编程

代码问题抛出

为了返回一个对象给业务调用里面的方法,写了一个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

;