• go基础7-常用接口及应用


    常用接口

    • sort.Interface

    sort包是go内置排序函数包.go的排序函数只是接口声明,不对具体类型和元素做假设.它通过sort.Interface接口约定具体排序序列,它需要知道三个参数长度,比较结果,交换方式.

    type Interface interface {
        Len() int
        Less(i, j int) bool // i, j are indices of sequence elements
        Swap(i, j int)
    }
    
    • http.Handler

    请求处理接口

    package http
    
    type Handler interface {
        ServeHTTP(w ResponseWriter, r *Request)
    }
    
    func ListenAndServe(address string, h Handler) error
    

    go的net/http包实现网络客户端,需要通过ListenAndServe监听服务地址及通过Handler进行请求分发.

    package http
    
    type HandlerFunc func(w ResponseWriter, r *Request)
    
    func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
        f(w, r)
    }
    

    HandlerFunc是实现Handler接口的函数类型.它通过ServeHTTP方法调用函数本身,来进行handler接口适配.

    db := database{"shoes": 50, "socks": 5}
    http.HandleFunc("/list", db.list)
    http.HandleFunc("/price", db.price)
    log.Fatal(http.ListenAndServe("localhost:8000", nil))
    
    // package http
    func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    	DefaultServeMux.HandleFunc(pattern, handler)
    }
    
    func (db database) list(w http.ResponseWriter, req *http.Request) {
        for item, price := range db {
            fmt.Fprintf(w, "%s: %s
    ", item, price)
        }
    }
    

    http.HandleFunc需要一个路径和一个handler函数,database实现了Handler接口,同时它又使用HandlerFunc适配器模式,来定义list方法进行方法适配.

    • error接口

    error用于返回异常信息,实际它只是一个接口.

    type error interface {
        Error() string
    }
    

    使用:

    1. errors.new函数.传入错误信息,返回一个新的error
    2. fmt.Errorf函数.封装了errors.New函数,并可以进行异常信息格式化
    3. syscall.Error.它提供了go语言底层系统的错误信息
    • 类型断言

    类型断言是接口值类型匹配判断.语法:x.(T);x表示接口类型,T表示类型;类型断言检查接口值x的动态类型是否和断言类型T匹配.

    匹配结果:

    1 T是具体类型.它会检查x的动态类型是否和T相同.成功则类型断言的结果是x的动态值(类型是T).失败抛出panic;

    var w io.Writer
    w = os.Stdout
    f := w.(*os.File)      // success: f == os.Stdout
    c := w.(*bytes.Buffer) // panic: interface holds *os.File, not *bytes.Buffer
    

    2 T是接口类型.它会检查x的动态来信是否满足T.成功则类型断言的结果是x的动态值(类型是T).失败抛出panic;区别就是前者x的类型是结果类型最大集,后者是T是类型的最大集.

    var w io.Writer
    w = os.Stdout
    rw := w.(io.ReadWriter) // success: *os.File has both Read and Write
    w = new(ByteCounter)
    rw = w.(io.ReadWriter) // panic: *ByteCounter has no Read method
    

    nil接口值的类型断言都是失败.针对T是接口类型,我们不需要针对T包含x的情形做断言,因为它类似于一次赋值操作.nil接口值例外.

    var w io.Writer
    var rw io.ReadWriter
    w = rw
    w = rw.(io.Writer) // fails only if rw == nil
    

    针对接口值动态类型不确定的情形,通常会检验它是否是特定类型.并通过额外结果来判断类型是否相同.

    if f, ok := w.(*os.File); ok {
        // ...use f...
    }
    

    这里f是结果值,ok是类型是否相同的boolean值,如果ok=true则进入判断方法体内.

    类型断言的应用:

    1 错误类型判断.
    2 询问行为.通过类型断言来判断是否存在特定行为,以满足个性化和统一处理的平衡.

    func formatOneValue(x interface{}) string {    
        if err, ok := x.(error); ok {    
            return err.Error()    
        }
        // ...all other types...    
    }    
    
    • 接口的应用
    1. 声明方法.表达接口和实现间的相似性,隐藏实现细节;重点在于方法,而不是具体类型实现.
    2. 值传递.接口值可以是任意类型,通过类型断言来动态区分类型与处理.该方式重点在于类型处理,而不在于接口的方法.因为没有隐藏细节所以也成为可辨识联合.

    值传递示例:

    func sqlQuote(x interface{}) string {
        switch x := x.(type) {
        case nil:
            return "NULL"
        case int, uint:
            return fmt.Sprintf("%d", x) // x has type interface{} here.
        case bool:
            if x {
                return "TRUE"
            }
            return "FALSE"
        case string:
            return sqlQuoteString(x) // (not shown)
        default:
            panic(fmt.Sprintf("unexpected type %T: %v", x, x))
        }
    }
    

    通过接口值interface{}来接收任意参数,类型断言x := x.(type)来判断具体参数类型,然后通过switch来进行处理筛选,定位到具体实现方法;

    使用原则:

    1. 两个及多个具体类型进行相同处理时才需要接口抽象,如果只有一个具体类抽象没有意义;
    2. 不同包中接口可以用来进行解耦;
    3. 接口定义应该在满足需求的前提下,尽可能小而简单,这样更利于使用;
    4. 对象和封装并不总是必须的,要分析具体使用情形;
  • 相关阅读:
    Apollo简介及项目集成
    Apollo源码打包及部署
    idea中的maven模块变成灰色的可能原因
    IDEA 不能显示项目里的文件结构
    Idea不能新建package的解决
    sourceTree 基础使用
    服务器负载均衡是什么意思?
    Spring中的代理模式
    ZooKeeper启动报错 JAVA_HOME is incorrectly set
    @Controller和@RestController的区别?
  • 原文地址:https://www.cnblogs.com/chengmuyu/p/13585724.html
Copyright © 2020-2023  润新知