go interface接口


自用留存

duck typing

  • 像鸭子走路,像鸭子叫,长得像鸭子,那么就是鸭子
  • 描述事物的外部行为而非内部结构
  • 和一个人或者事务互动,不管是什么人,什么事务,只要提供指定能力,我们与能力互动
  • 严格说go属于结构化类型系统,类似duck typing

python

def download(retriever):
    return retriever.get("www.baidu.com")
  • 运行时 才知道传入的retriever有没有get
  • 需要注释来说明接口

c++

template <class R>
string download(const R& retriever) {
	return retriever.get("www.baidu.com");
}
  • 编译时才知道传入的retriever有没有get
  • 需要注释来说明接口

java

<R extends Retriever>
String download(R r) {
	return r.get("www.baidu.com")
}
  • 传入参数必须实现Retriever接口
  • 不是duck typing

go

type Retiever interface {
	Get(url string) string
}
func download(r Retiever) string {
	return r.Get("www.baidu.com")
}
  • 同时具有python,c++的duck typing的灵活性
  • 又具有java类型的检查

go接口定义和实现:

使用者–>实现者

  • 接口由使用者定义
  • 接口实现是隐式的
  • 只要实现接口里面的方法
package main

import (
	"awesome/mock"
	"awesome/retr"
	"fmt"
)

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 fake baidu"}
	r = retr.Retriever{}
	fmt.Println(download(r))
}
package retr

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

type Retriever struct {
	UserAgent string
	TimeOut   time.Duration
}

func (receiver Retriever) Get(url string) string {
	resp, err := http.Get(url)
	if err != nil {
		panic(err)
	}
	result, err := httputil.DumpResponse(resp, true)
	resp.Body.Close()
	if err != nil {
		panic(err)
	}
	return string(result)
	}
package mock

type Retriever struct {
	Contents string
}

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

go接口的值类型

package main

import (
   "awesome/mock"
   "awesome/retr"
   "fmt"
)

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 fake baidu"}
   fmt.Printf("%T %v\n", r, r)
   r = retr.Retriever{}
   fmt.Printf("%T %v\n", r, r)
   //fmt.Println(download(r))
}
//mock.Retriever {this is fake baidu}
//retr.Retriever { 0s}  //package retr 中 Retriever struct 第一个值默认是空,time默认是0s


package main

import (
   "awesome/mock"
   "awesome/retr"
   "fmt"
   "time"
)

type Retriever interface {
   Get(url string) string
}

func download(r Retriever) string {
   return r.Get("https://www.baidu.com")
}
func main() {
   r := retr.Retriever{
   	"Google29",   //UserAgent   string
   	time.Hour,   //TimeOut      time.Duration
   }
   fmt.Printf("%T %v\n", r, r)
}
//retr.Retriever {Google29 1h0m0s}
package retr
import (
-
)
type Retriever struct {
	UserAgent string
	TimeOut   time.Duration
}
func (receiver *Retriever) Get(url string) string { //指针
...
}
-----------------------------------------------------
package main
import (
...
)
type Retriever interface {
...
}
func download(r Retriever) string {
...
}
func main() {
...
	r = &retr.Retriever{ //获取指针
...
	}
	fmt.Printf("%T %v\n", r, r)
	//fmt.Println(download(r))
}
//*retr.Retriever &{Google29 1h0m0s}//类型是指针类型 *retr.Retriever 值是指针 &{Google29 1h0m0s}

func inspect(r Retriever) {
	switch v := r.(type) {
	case mock.Retriever:
		fmt.Println("contents:", v.Contents)
	case *retr.Retriever:
		fmt.Println("UserAgent:", v.UserAgent)
	}
}
//*retr.Retriever &{Google29 1h0m0s}
//UserAgent: Google29       
func main() {
...
	//type assertion
	if realRetriever, ok := r.(*retr.Retriever); ok {
		fmt.Println(realRetriever.TimeOut)
	} else {
		fmt.Println("not a retr retriever")
	}
}
//1h0m0s //默认1h

接口变量里面有什么

  • 接口变量自带指针
  • 接口变量同样采用值传递,几乎不需要使用接口的指针
  • 指针接收者实现只能以指针方式使用;值接收者即可
    在这里插入图片描述

查看接口变量

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

go接口组合

package main

import (
	"awesome/mock"
	"awesome/retr"
	"fmt"
	"time"
)

type Retriever interface {
	Get(url string) string
}

type Poster interface {
	Post(url string, form map[string]string) string
}

func post(poster Poster) {
	poster.Post("https://www.baidu.com", map[string]string{
		"name": "baidu",
		"lang": "go",
	})
}

type RetrieverPoster interface {
	Retriever
	Poster
}

func session(s RetrieverPoster) string {
	s.Post(url, map[string]string{
		"contents": "show this is true",
	})
	return s.Get(url)
}

const url = "https://www.baidu.com"

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

func main() {
	var r Retriever
	retriever := mock.Retriever{"show this is false"}
	r = &retriever
	//type assertion
	if mockRetriever, ok := r.(*mock.Retriever); ok {
		fmt.Println(mockRetriever.Contents)
	} else {
		fmt.Println("not a mock retriever")
	}
	fmt.Println("try a session")
	fmt.Println(session(&retriever))

}
//try a session  
//show this is true
-----------------------------------
package mock

type Retriever struct {
	Contents string
}

func (r *Retriever) Post(url string, form map[string]string) string {
	//TODO implement me
	r.Contents = form["contents"]
	return "ok"
}

func (r *Retriever) Get(url string) string {
	return r.Contents
}
-------------------------------------
package retr

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

type Retriever struct {
	UserAgent string
	TimeOut   time.Duration
}

func (receiver *Retriever) Get(url string) string {
	resp, err := http.Get(url)
	if err != nil {
		panic(err)
	}
	result, err := httputil.DumpResponse(resp, true)
	resp.Body.Close()
	if err != nil {
		panic(err)
	}
	return string(result)
}


特殊接口

stringer()
io.Reader()
io.Writer()

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)

func printFile(filename string) {
	file, err := os.Open(filename)
	if err != nil {
		panic(err)
	}
	printFileContents(file)
}
func printFileContents(reader io.Reader) {
	scanner := bufio.NewScanner(reader)
	for scanner.Scan() {
		fmt.Println(scanner.Text())
	}
}

func main() {
	printFile("testdoc.txt")
	s := `abcde"qwe"
asd
ffff`
	printFileContents(strings.NewReader(s))
}
/*
文本内容
abcde"qwe"
asd
ffff
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值