第七章-接口

flag包,io包 fmt包
接口类型是对其他类型行为的抽象和概括,因为接口类型不会和特定的实现细节绑定在一起,通过这种抽象方式,我们可以让我们的函数更加灵活和更具有适应能力。
go语言的接口类型的特点在于,它的实现方式是隐式的,也就是说,我们没有必要对于给定的具体类型定义所有满足的接口类型;简单地拥有一些必须的方法就足够了。这种涉及可以让你创建一个新的接口类型满足已经存在的具体类型,却不会改变这个类型的定义;


基础理解:接口类型是一种抽象的类型。它不会暴露出它所代表的对象的内部值的结构和这个对象支持的基础操作的集合;它只会展示出它们自己的方法。也就是说当你有看到一个接口类型的值时,你不知道它是什么,唯一知道的就是可以通过它来做什么。
一个类型可以自由的使用另一个满足相同接口的类型来进行替换被称作可替换性,(LSP里式替换)这是一个面向对象的特征。

接口类型
接口类型具体描述了一系列方法的集合,一个实现了这些方法的具体类型是这个接口类型的示例。
io.Writer类型是用的最广泛的接口之一,因为它提供了所有的类型写入bytes的抽象。接口的实现允许接口内嵌例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//基础声明
type Read interface{
Read(p []byte)(n int,err error)
}
type Closer interface{
Close() error
}
//内嵌声明:
type ReadWriter interface{
Reader
Writer
}
//混合声明:
type ReadWriter interface{
Read(p []byte)(n int,err error)
Writer
}


####实现接口的条件
一个类型如果拥有一个接口需要的所有方法,那么这个类型就实现了这个接口。例如,*os.File 类型实现了io.Reader ,Witer ,Closer,和ReaderWiter接口等。
几个特殊的接口
空接口 interface{}没有任何实现方法,所以可以说任何变量都实现了空接口。之后的类型断言用于判断变量类型的时候,这个点就应用的很广泛。
flag.value接口这个几口帮助命令行标记定义新的符号。
它的构成

1
2
3
4
5
package flag
type Value interface{
String() string
Set(string) error
}

sort.Interface接口
排序操作和字符串格式化一样是很多程序经常使用的操作。尽管一个最短的快排只要15行就可以搞定,但是一个健壮的实现,需要更多的代码,并且我们不希望每次都去拷贝这种方法。
sort包内置的提供了根据一些排序函数来对任何序列排序的功能。go中提供了sotr.Sort函数,它不会对任何具体的序列和它的元素做假设,相反它使用了一个接口类型sort.Interface来指定通用的排序算法和可能被排序到序列类型的约定。这个接口的实现由序列的具体表示和它希望排序的元素决定。序列的表示通常是一个切片。
sort.Interface的本体方法为:

1
2
3
4
5
6
package sort
type Interface interface{
Len() int// 长度
Less(i,j int) bool //对比函数,确定两者谁大
Swap(i,j int) //排序,按照升序降序 ,对换ij下标中的值。
}

对于字符串切片的排序经常用到,所以sort包提供了StringSlice类型,也提供了Strings函数能让调排序简化为:sort.Strings(names)
sort包中提供Reverse函数将排序顺序从接口定义的less函数转换成逆序。
reverse的本体如下:

1
2
3
type reverse struct {Interface}
func (r reverse) Less(i,j int) bool {return r.Interface.Less(j,i)}
func Reverse(data Interface) Interface { return reverse{data}}

它的len和swap函数隐式的由原有内嵌的s.Interface提供。
检查一个序列是否需要排序使用函数sort.IsSorted

####http.Handler 接口
net/http包实现了网络客户端与服务器的操作,
基础服务:
ListenAndServe(address string, h Handler) error 会一直执行,知道这个服务运行因为一个错误而失败,它的返回值一定是一个非空的错误。
address 是一个类似 “localhost:8080”的服务器地址,Handler则是请求处理的函数。

Handler 接口需要实现一个ServerHttp(w ResponseWriter, r *Request) 方法
该方法实现接收http参数与处理。

Handler接收所有来自LisetenAndServe的处理,分路径处理的话就需要涉及到:r .URL.Path 变量。可以用该变量做路由分流所有的http请求。
至此基础的golang http服务流程就基本完事了
下面我们说说个更加简单的url配置方式serveMux^^
net/http包提供一个请求多路器serveMux 来简化URL和handlers的联系。

error接口
error类型是一个接口类型,这个类型有一个单一的返回错误信息的方法 Error 本体:

1
2
3
4
5
6
7
8
type error interface {
Error() string
}
//error 包 只有四行
package errors
func New(text string) errpr {return &errorString{text}}
type errorString struct{text string}
func (e *errorString) Error()string {return e.text}

errors.New 函数很少调用,因为有一个方便的封装函数fmt.Errorf,它会处理字符串格式化 除了基础的errorString 还有errno等表示错误数字小心的包。


####接口值
概念上讲接口的值,接口值,由两部分组成,具体的类型和那个类型的值;合起来被称为接口值,分别被称为接口的动态类型和动态值。
在go中变量总是被一个定义明确的值初始化,即使接口类型也不例外。对于一个接口的零值就是它的类型和值的部分都是nil。这种零值接口允许w==nil进行判断,但是直接用零值接口调用任何方法,都会产生panic。
接口值是可以比较的,但是如果两个接口值的动态类型相同,但是这个类型是不可比较的类型(类似切片),它们比较就会失败产生panic。所以基于这点接口类型比较特殊,它时而能比较(普通变量)时而不能比较(接口值变化),所以在处理接口值比较的时候我们必须处理可能发生的panic,规避这种潜在的风险,避免因为类型转变导致的panic。

注意:一个包含nil指针的接口不是nil接口
一句话来说就是,一个不包含任何值的接口值和一个刚好包含nil指针的接口值是不同的。因为不包含任何值的接口值的动态类型是nil而包含nil指针的接口值的动态类型是指针。

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器