• 学习Golang的接口


    前言

    接口是一种限制一种约定
    要求对象类型实现了某些方法  

    第一个例子 

    文件1:infra.go

    这是自定义的infra包

    在Go语言中 结构体其实就是(对象)类的载体

    在文件1中

    实现了结构体 Retriever

    并且实现了方法 Get

            Get方法符合规定的参数要求:一个传入string参数 返回一个string参数

    1. package infra
    2. import (
    3. "io/ioutil"
    4. "net/http"
    5. )
    6. type Retriever struct {
    7. }
    8. func (Retriever) Get(url string) string {
    9. resp, err := http.Get(url)
    10. if err != nil {
    11. panic(err)
    12. }
    13. defer resp.Body.Close()
    14. bytes, _ := ioutil.ReadAll(resp.Body)
    15. return string(bytes)
    16. }

    文件2: main.go

    调用我们定义的infra包

    在文件2中

    type retriever interface{

            Get(string)string

    }

    这是定义了一个接口

    观察发现 infra包中的 Retriever结构体确实按照要求实现了Get方法

    因此 可以用接口类型 retriever 定义变量 something

    var something retriever

    这里要求 something 按照要求实现了Get方法

    1. package main
    2. import (
    3. "fmt"
    4. "infra"
    5. )
    6. func getRetriever() infra.Retriever {
    7. return infra.Retriever{}
    8. }
    9. //接口是一种限制一种约定
    10. //要求接收的对象类型实现了某些方法
    11. type retriever interface {
    12. // Get 在这里指定要求实现哪些具体的方法
    13. Get(string) string
    14. }
    15. func main() {
    16. //Something that can "Get"
    17. var something retriever = getRetriever()
    18. fmt.Println(something.Get("https://www.baidu.com"))
    19. }

    运行效果 

    深入分析

    关于接口的讨论:
    应当关注 实现类 的外部行为而非内部结构

    认识Duck Typing的概念

    duck typing
    一个东西究竟是不是鸭子

    取决于它的能力

    游泳起来像鸭子(不同的场景有不同的要求

    叫起来也像鸭子(不同的场景有不同的需要

    那么就可以是鸭子

    对比不同语言

    python 只有在运行时才能知道
    使用的对象是否按照接口的要求实现了某些方法
    需要通过注释约定接口的要求
    对传入的对象参数没有类型检查

    C++ 只有在编译时才能知道
    使用的对象是否按照接口的要求实现了某些方法
    需要通过注释约定接口的要求
    对传入的对象参数没有类型检查

    JAVA 在写代码时就能发现
    使用的对象是否按照接口的要求实现了某些方法
    传入的参数类型被确定 有参数类型检查 不必通过注释说明
    但并不是duck typing的理想概念 不够灵活
    例如JAVA在更新拓展接口时 往往需要大量的代码修改

    Golang是面向接口的编程语言
    接口由使用者定义而非实现者定义
    实现了指定的方法就能直接被接口类型引用(调用)

    结论:Go语言的接口是一组方法的集合

    Go语言颠覆性的接口设计

    认识侵入式接口与非侵入式接口
    侵入式:JAVA C++
    非侵入式:Golang
    侵入式:实现类需要明确指出自己实现了某个接口
    C++     实现的类名 : public 接口名 (虚继承)
    JAVA   实现的类名 implements 接口名

    非侵入式:只要实现了接口规定的一组方法 就可以直接被接口类型调用

    实现类不需要显示声明自己实现了某些接口

    第二个例子 

    1. package main
    2. import (
    3. "fmt"
    4. )
    5. //定义一个对象 实现接口
    6. type implement struct {
    7. Contents string
    8. }
    9. func (i implement) Get(url string) string {
    10. return i.Contents
    11. }
    12. type Retriever interface {
    13. Get(url string) string
    14. }
    15. func download(r Retriever) string {
    16. return r.Get("https:// www.baidu.com")
    17. }
    18. //download是使用者
    19. //r是实现者
    20. func main() {
    21. var r Retriever = implement{"Hello World"}
    22. fmt.Println(download(r))
    23. }

    分析程序的执行过程

    1.定义了一个implement对象

    2.为implement对象绑定了方法Get

            传入一个string参数 返回一个string参数

    3.定义一个Retriever的接口类型

            要求实现Get方法

            传入一个string参数 返回一个string参数

    4.实现download函数 传入Retriever接口类型的变量

            返回Get方法的调用结果

    5.在main函数中 初始化了一个implement对象

    6.将初始化的implement对象赋值给接口类型(Retriever)变量(r)

    7.download函数调用 打印Hello World

    有趣之处

    Get方法的具体实现 并不是去获取www.baidu.com的相关信息

    而是直接打印Hello World

    这就印证了:

    1.只要实现接口的方法 就可以直接被接口类型调用

    2.关注对象的能力 而非内部构造与具体实现

    第三个例子

    接口类型模拟队列

    interface{}在Go语言中可以表示任何类型
    类似于C++的模板编程 区别在于 这个Queue切片可以同时存不同的类型
    缺点:只有在运行时才能知道是否发生错误

    1. package main
    2. import "fmt"
    3. //interface{}在Go语言中可以表示任何类型
    4. //类似于C++的模板编程 区别在于这个Queue可以存不同的类型
    5. //缺点 只有在运行时才能知道是否发生错误
    6. type Queue []interface{}
    7. func (q *Queue) Push(v interface{}) {
    8. *q = append(*q, v)
    9. }
    10. func (q *Queue) Pop() interface{} {
    11. head := (*q)[0]
    12. *q = (*q)[1:]
    13. return head
    14. }
    15. func (q *Queue) IsEmpty() bool {
    16. return len(*q) == 0
    17. }
    18. func main() {
    19. var q Queue
    20. q.Push("ABC")
    21. q.Push(999)
    22. q.Push(13.14)
    23. fmt.Println(q.Pop())
    24. fmt.Println(q.Pop())
    25. fmt.Println(q.Pop())
    26. }

    运行效果

  • 相关阅读:
    三、Keil安装芯片包、下载固件库、建立STM32工程模板
    AI对网络安全的影响与挑战
    【附源码】Python计算机毕业设计图书销售管理系统
    MIKE水动力笔记12_数字化海图1之提取确值水深点
    [GYCTF2020]Ez_Express
    网络安全(黑客)自学笔记
    react创建项目后运行npm run eject无法暴露配置文件(已解决!!!)
    setTimeout与setInterval区别
    细说React组件性能优化
    VLC命令行实例
  • 原文地址:https://blog.csdn.net/u014285914/article/details/126141084