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