Learn Go (六) 面向接口

duck typing

许多编程语言都支持 Duck Typing ,通常 Duck Typing 是动态编程语言用来实现多态的一种方式

duck.png

Duck Typing 的原话是,走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么它就是一只鸭子。描述事物的外部行为而非内部结构

Demo

  • Python

    def download(retriever):
        return retriever.get("www.imooc.com")
    

    运行时才知道传入的 retriever 有没有 get; 需要注释来说明接口

  • c++

    template 
    string download(const R& retriver) {
        retrun retriever.get("www.imooc.com");
    }
    

    编译时才知道传入的 retriever 有没有 get; 需要注释来说明接口

  • java

    java 是没有 duck typing, 有类似的

    
    String download(R r) {
        return r.get("www.imooc.com")
    }
    

    传入的参数必须实现 Retriever 接口; 不是 duck typing

  • go

    javaduck typing

    type R interface {
    
        Get(url string) string
    }
    

接口

定义

package mock

type Retriever stuct {
    Contents string
}

func (r Retriever) Get(url string) string {
    return r.Contents
}

  • 接口由使用者定义

    // 定义接口
    type Retriever interface {
        Get(url string) string
    }
    
    
    // 使用 
    func download(r Retriever) string {\
        return r.Get("https://www.baidu.com")
    }
    
  • 接口实现是隐式的

    func main() {
        var r Retriever
        // 调用接口
        r = mock.Retriever("this is hello")
    }
    
  • 只要实现接口里的方法

接口的值类型

打印出类型, 和 value

func main() {
        var r Retriever
        // 调用接口
        r = mock.Retriever("this is hello")
        fmt.Printf("%T %v\n", r, r)  // 结果 mock.Retriever {this is hello }
    }

  • 接口变量里有什么

    value.png
    image.png
    • 接口变量自带指针
    • 接口变量同样采用值传递, 几乎不需要使用接口的指针

接口变量

  • 表示任何类型: interface{}
  • Type Assertion
  • Type Switch

接口组合

可以将多个接口组合成一个新的接口, 然后通过组合后的接口, 调用里面每个接口元素的方法

// 接口一
type Retriever interface {
    Get(url string) string
}

// 接口二
type Poster interface {
    Post(url string, form map[string]string) string
}

// 接口组合
type RetrieverPoster interface {
    Retriever
    Poster
}

// 调用
func session(s RetrieverPoster) string {
    s.Post(url, map[string]string{
        "contents" : "hello duck typing"
    })
    
    return s.Get(url)
}

常用系统接口

  • Stringer

    方法被用于打印传递的值, 格式和未格式化的字符串打印

  • Reader

    Reader 实现了 io.Reader、io.ReaderAt、io.ByteReader、io.ByteScanner、
    io.RuneReader、io.RuneScanner、io.Seeker 和 io.WriterTo 通过读取接口
    从一个字符串。
    Reader 的零值的操作类似于空字符串的 Reader。

    func printFileContents(reader io.Reader) {
       scanner := bufio.NewScanner(reader)
    
       for scanner.Scan() {
          fmt.Println(scanner.Text())
       }
    }
    
  • Writer

    Writer 是封装了基本 Write 方法的接口。

    Write 将 len(p) 个字节从 p 写入底层数据流。
    它返回从 p (0 <= n <= len(p)) 写入的字节数
    以及任何导致写入提前停止的错误。
    如果 Write 返回 n < len(p),则它必须返回一个非 nil 错误。
    写入不得修改切片数据,即使是临时修改。

你可能感兴趣的:(Learn Go (六) 面向接口)