golang-接口

爱吃豆包 · · 694 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Go语言规定,只要实现了接口里面的方法,就是该接口的实现类

接口变量里面有什么?
实现者的类型 和 实现者的指针

接口变量自带指针
接口变量同样采用值传递,几乎不需要使用接口的指针
指针接收者实现只能以指针方式使用;值接收者都可以用

定义一个接口

package main

import (
    "fmt"
    "interfaces/mock"
    "interfaces/real"
    "time"
)

/**
    Go语言规定,只要实现了接口里面的方法,就是该接口的实现类

    接口变量里面有什么?
    实现者的类型 和 实现者的指针

    接口变量自带指针
    接口变量同样采用值传递,几乎不需要使用接口的指针
    指针接收者实现只能以指针方式使用;值接收者都可以用
    
    。。。。
    type Retriever struct {}
    type Retriever string
    等等,都可以算是这个 Retriever 接口的实现类
    。。。。

 */

// 声明一个接口类型
type Retriever interface {
    // Get方法
    // 一个未实现的方法
    Get(url string) string
}

func download(r Retriever) string {
    return r.Get("http://www.imooc.com")
}

func main() {
    // 声明接口类型,但不分配内存
    var r Retriever
    // 获取 一个实现类,并赋值给 r
    // 因为 mock.Retriever 实现了 Retriever 接口里的方法,所以他就是一个实现类
    // 这里相当于就是把 mock.Retriever 值复制了一份,然后赋值给 r
    r = mock.Retriever{"这是一个百度网页"}

    // 输出是什么类型,也就是实现类型,以及值
    fmt.Printf("%T %v\n",r ,r)

    // 什么接口类型, 但不分配内存
    var rb Retriever
    // 实现类
    // 不建议使用接口指针,因为本身就自带了指针, 可以直接用指针
    rb = &real.Retriever{
        UserAgent: "Mozilla/5.0",
        TimeOut: time.Minute,
    }

    // 输出是什么类型,也就是实现类型,以及值
    fmt.Printf("%T %v\n",rb ,rb)

    //fmt.Println(download(r))
    //fmt.Println(download(rb))

    // 判断是什么类型
    inspect(rb)

    // 类型断言
    // 如果是指针就要用指针, 普通的就直接用,比如:mock.Retriever
    realRetriever, ok := r.(*real.Retriever)
    if ok {
        fmt.Println(realRetriever.TimeOut)
    } else {
        fmt.Println("这不是 mock.Retriever 类型")
    }


}

// 判断是什么类型
func inspect(r Retriever)  {

    // 判断是什么样的类型
    switch v := r.(type) {
    case mock.Retriever:
        fmt.Println("Contents: ", v.Contents)
    case *real.Retriever:
        fmt.Println("UserAgent: ", v.UserAgent)

    }
}


接口实现1

package mock

/**
    这里是一个实现类,结构名称最好和那个接口名称一样
    然后在实现那个接口里面的 Get 方法

    Go语言规定,只要实现了接口里面的方法,就是该接口的实现类

 */

type Retriever struct {
    // 结构体里面的属性
    Contents string
}

// 实现接口 Retriever 里面的方法 Get
func (r Retriever) Get(url string) string {
    // 实现的方法体
    return r.Contents
}

接口实现 2

package real

import (
    "net/http"
    "net/http/httputil"
    "time"
)

type Retriever struct {

    // 数据
    UserAgent string

    // 超时时间
    TimeOut time.Duration

}

// 这里指定了是指针,在外面就只能用指针开接收
// 不建议使用接口指针,因为本身就自带了指针
func (r Retriever) Get(url string) string {

    resp, err := http.Get(url)
    if err != nil {
        // 抛出一个错误
        panic(err)
    }

    // 第一个参数,把返回来的resp放入,第二个参数,是否返回body体,为true
    result, err := httputil.DumpResponse(resp, true)
    // 关闭请求
    resp.Body.Close()

    if err != nil {
        panic(err)
    }

    // 因为返回的是byte切片,所以需要转换为string
    return string(result)
}



main方法

 package main

import (
    "fmt"
    "interfaces/mock"
    "interfaces/real"
    "time"
)

/**
    Go语言规定,只要实现了接口里面的方法,就是该接口的实现类

    接口变量里面有什么?
    实现者的类型 和 实现者的指针

    接口变量自带指针
    接口变量同样采用值传递,几乎不需要使用接口的指针
    指针接收者实现只能以指针方式使用;值接收者都可以用

 */

// 声明一个接口类型
type Retriever interface {
    // Get方法
    // 一个未实现的方法
    Get(url string) string
}

func download(r Retriever) string {
    return r.Get("http://www.imooc.com")
}

func main() {
    // 声明接口类型,但不分配内存
    var r Retriever
    // 获取 一个实现类,并赋值给 r
    // 因为 mock.Retriever 实现了 Retriever 接口里的方法,所以他就是一个实现类
    // 这里相当于就是把 mock.Retriever 值复制了一份,然后赋值给 r
    r = mock.Retriever{"这是一个百度网页"}

    // 输出是什么类型,也就是实现类型,以及值
    fmt.Printf("%T %v\n",r ,r)

    // 什么接口类型, 但不分配内存
    var rb Retriever
    // 实现类
    // 不建议使用接口指针,因为本身就自带了指针, 可以直接用指针
    rb = &real.Retriever{
        UserAgent: "Mozilla/5.0",
        TimeOut: time.Minute,
    }

    // 输出是什么类型,也就是实现类型,以及值
    fmt.Printf("%T %v\n",rb ,rb)

    //fmt.Println(download(r))
    //fmt.Println(download(rb))

    // 判断是什么类型
    inspect(rb)

    // 类型断言
    // 如果是指针就要用指针, 普通的就直接用,比如:mock.Retriever
    realRetriever, ok := r.(*real.Retriever)
    if ok {
        fmt.Println(realRetriever.TimeOut)
    } else {
        fmt.Println("这不是 mock.Retriever 类型")
    }


}

// 判断是什么类型
func inspect(r Retriever)  {

    // 判断是什么样的类型
    switch v := r.(type) {
    case mock.Retriever:
        fmt.Println("Contents: ", v.Contents)
    case *real.Retriever:
        fmt.Println("UserAgent: ", v.UserAgent)

    }
}



有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:爱吃豆包

查看原文:golang-接口

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

694 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传