接口
Go接口定义了方法后,其它类型只要实现了这些方法就是实现了接口。Go语言中接口类型的独特之处在于它是满足隐式实现的鸭子类型。所谓鸭子类型说的是:只要走起路来像鸭子,叫起来也像鸭子,那么就可以把它当作鸭子。
type Person interface {
speak()
}
type Student struct {
}
type Worker struct {
}
func (student Student) speak(){
println("I am student")
}
func (worker Worker) speak(){
println("I am worker")
}
func main() {
var person Person
person=Worker{}
person.speak()//I am worker
person=Student{}
person.speak()//I am student
}
有时候对象和接口之间太灵活了,导致我们需要人为地限制这种无意之间的适配。常见的做法是定义一个含特殊方法来区分接口。比如runtime包中的Error接口就定义了一个特有的RuntimeError方法,用于避免其它类型无意中适配了该接口:
type Error interface {
error
// RuntimeError is a no-op function but
// serves to distinguish types that are run time
// errors from ordinary errors: a type is a
// run time error if it has a RuntimeError method.
RuntimeError()
}
在Go中只有interface的类型和值都为nil时,interface==nil才为true,所以我们在函数中返回一个interface时,如果想返回nil,需要直接返回nil而不是返回结构体nil指针。
func main() {
var data *byte
var data2 interface{}
data2=data
println(data2==nil)//false
data2=nil
println(data2==nil)//true
}
类型断言
类型断言是将接口类型转换为具体类型,类型断言分为安全类型断言和非安全类型断言,非安全类型断言失败时会发生异常,安全类型断言则可以通过返回值判断类型断言是否失败。
type MyInterface interface {
sayHello()
}
type MyStruct struct {
}
func (obj *MyStruct) sayHello(){
println("hello")
}
func NewMyStruct() MyInterface{
return &MyStruct{}
}
func main() {
//安全类型断言
obj1,ok:=NewMyStruct().(*MyStruct)
if ok{
obj1.sayHello()
}
//非安全类型断言
obj2:=NewMyStruct().(*MyStruct)
obj2.sayHello()
}
错误
错误是Go的内置接口,其定义如下:
type error interface {
Error() string
}
对于简单的错误,我们可以使用内置的errors.New生成一个errorString,对于复杂的错误,我们可以新建一个结构体实现error接口。
func divide(varDividee int, varDivider int) (int,error) {
if varDivider == 0 {
return 0,errors.New("the divider is zero")
} else {
return varDividee / varDivider, nil
}
}
func main(){
result,err:=divide(10,0)
if err!=nil{
fmt.Println(err)
}else{
fmt.Printf("result=%d\n",result)
}
}
网友评论