golang interface 接口类型值
package main
import "fmt"
type Service interface {
Name()
}
type MySql struct{}
func (MySql) Name() {}
func test(s Service) {
// 因为 m2 赋值给了 s
// s 的动态类型为 *MySql,其值为 nil,也即 s 为 (*MySql)(nil),故此处判断为 true
if s != nil {
fmt.Printf("value: %v type: %T\n", s, s)
}
}
func main() {
// 变量的类型在声明时指定且不能改变称为静态类型
// 接口类型的静态类型就是接口本身,接口没有静态值,它指向的是动态值
// s 的动态值为 nil 且为静态类型 Service
var s Service
fmt.Printf("value: %v type: %T\n", s, s)
// 这个赋值过程调用了一个具体类型到接口类型的隐式转换,这和显式的使用 Service(MySql) 是等价的
// s 的动态类型为 MySql,其值为结构体 {}
s = MySql{}
fmt.Printf("value: %v type: %T\n", s, s)
// m1 为静态类型 MySql,其值为结构体 {}
var m1 MySql
fmt.Printf("value: %v type: %T\n", m1, m1)
// m2 为静态类型 *MySql,其值为 nil
var m2 *MySql
fmt.Printf("value: %v type: %T\n", m2 == nil, m2)
// s 为动态类型 *MySql,其值为 nil,也即 s 为 (*MySql)(nil)
s = m2
test(m2)
// 当且仅当动态值和动态类型都为 nil 时,接口类型值才为 nil
fmt.Printf("value: %v value: %v type: %T\n", s == nil, s == (*MySql)(nil), s)
}
/*
value: <nil> type: <nil>
value: {} type: main.MySql
value: {} type: main.MySql
value: true type: *main.MySql
value: <nil> type: *main.MySql
value: false value: true type: *main.MySql
*/