go语言学习笔记三-接口
接口约定
接口是一种约定,约定方法参数并不关心具体的细节的实现。使用接口类型作为方法参数时,可以增加其对应的灵活性。很多设计模式都是基于接口,例如策略模式等
接口类型
接口类型描述了一系列方法的集合,一个实现了这些方法的具体类型是这个接口类型的实例。
新的类型可以通过组合已有的接口来定义。和结构体的组合一致
实现接口的条件
一个类型如果拥有了一个接口所需要的所有方法,那么这个类型就实现了这个接口,一个类型时刻是实现多个接口。
每一个具体类型的组基于他们相同的行为可以表示成一个接口类型。不像基于类语言,他们一个类实现的接口集合需要进行显示的定义
flag.Value接口
其具体有2个方法
package flag
// Value is the interface to the value stored in a flag.
type Value interface {
String() string
Set(string) error
}
实现这2个方法就可以与flag中的一起使用,通过命令行来进行参数的赋值,以及对应的赋值操作
接口值
接口值,由两个部分组成,一个具体的类型和那个类型的值。它们被称为接口的动态类型和动态值。他们被称为接口的动态类型和动态值。一个接口的零值,他的类型和值的部分都是nil。
接口值可以使用和!=来进行比较。接口值相等需要动态类型和动态值使用时都为true。有的接口类型是不可比较例如切片,映射类型,和函数
一个包含nil指针的接口不是nil接口,例如下面代码会发生panic,因为out !=nil 其动态类型是*bytes.Buffer,值为nil
var out *bytes.Buffer
if out != nil {
out.Write([]byte("done!\n"))
}
,将以上代码改为var buf io.Writer 即可
sort.Interface接口
其主要包含一下三个方法,想使用其排序实现以下接口实现即可
package sort
type Interface interface {
Len() int
Less(i, j int) bool // i, j are indices of sequence elements
Swap(i, j int)
}
个人觉得这三个接口定义的很恰当,其reverse类型在次基础上用的也比较好,如下 出了less是将其下标更改了,其他还是使用其原函数
package sort
type reverse struct{ Interface } // that is, sort.Interface
func (r reverse) Less(i, j int) bool { return r.Interface.Less(j, i) }
func Reverse(data Interface) Interface { return reverse{data} }
http.Handler接口
通过实现这个接口,来接受对应的网络客户端请求
package http
type Handler interface {
ServeHTTP(w ResponseWriter, r *Request)
}
func ListenAndServe(address string, h Handler) error
error接口
type error interface {
Error() string
}
创建一个error最简单的方法就是调用errors.New函数,它会根据传入的错误信息返回一个新的error。整个errors包仅只有4行:
package errors
func New(text string) error { return &errorString{text} }
type errorString struct { text string }
func (e *errorString) Error() string { return e.text }
承载errorString的类型是一个结构体而非一个字符串,这是为了保护它表示的错误避免粗心(或有意)的更新。
类型断言
类型断言是一个使用在接口值上的操作。语法上它看起来像x.(T)被称为断言类型,这里x表示一个接口的类型和T表示一个类型。一个类型断言检查它操作对象的动态类型是否和断言的类型匹配。如果失败失败,则会抛出panic。例如如下操作
var w io.Writer = os.Stdout
f, ok := w.(*os.File) // success: ok, f == os.Stdout
b, ok := w.(*bytes.Buffer) // failure: !ok, b == nil