formatLoopformatLoopformatLoop#### 接口的概念
main.go
package main
import (
"ZipTest_backend/infra"
"ZipTest_backend/testing"
"fmt"
)
// func traverse(url string) []byte {
// resp, err := http.Get(url)
// if err != nil {
// panic(err)
// }
// defer resp.Body.Close()
// bytes, _ := ioutil.ReadAll(resp.Body)
// return bytes
// }
func getRetriever() infra.RetrieverBody {
return infra.RetrieverBody{}
}
func getRetrieverTest() testing.Retriever {
return testing.Retriever{}
}
func main() {
// // traverse := infra.Retriever{}
// var traverse infra.Retriever = getRetriever()
// fmt.Println(string(traverse.Get("https://www.imooc.com")))
// var traverseTest testing.Retriever = getRetrieverTest()
// fmt.Println(string(traverseTest.Get("https://www.imooc.com")))
var trieverInterface = infra.Retriever()
fmt.Println(trieverInterface.Get("https://www.imooc.com"))
}
infra/infra.go
package infra
import (
"io/ioutil"
"net/http"
)
type RetrieverInterface interface {
Get(string) string
}
type RetrieverBody struct{}
// func ()
func Retriever() RetrieverInterface {
return RetrieverBody{}
}
func (RetrieverBody) Get(url string) string {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
bytes, _ := ioutil.ReadAll(resp.Body)
return string(bytes)
}
testing/retriever.go
package testing
type Retriever struct{}
func (Retriever) Get(url string) string {
return "fake content"
}
- 强类型语言:熟悉接口的概念
- 弱类型语言:没有(少)接口的概念
- curl命令是linux\mac系统上请求http链接的命令,会将整个网页的源码打印出来
- 模块化
duck typing的概念
- “像鸭子走路,像鸭子叫(长得像鸭子),那么就是鸭子”
- 描述事务的外部行为而非内部结构
- 严格说go属于结构化类型系统,类似duck typing
- python——运行时才知道传入的retriever有没有get
- python——需要注释来说明接口
- C++——编译时才知道传入的retriever有没有get
- C++——需要注释来说明接口
- JAVA没有duck typing
- JAVA有类似的代码
- JAVA——传入的参数必须实现retriever的接口
- GO——同时需要Readable、Appendable
- GO——同时具有python,c++的duck typing的灵活性
- GO——又具有java的类型检查
接口的定义和实现
main.go
package main
import (
"ZipTest_backend/mock"
"ZipTest_backend/real"
"fmt"
)
type Retriever interface {
Get(string) string
}
func download(r Retriever) string {
return r.Get("http://www.imooc.com")
}
func main() {
var r Retriever
r = mock.Retriever{"this is a fake imooc.com"}
fmt.Println(download(r))
var realR Retriever = real.Retriever{}
fmt.Println(download(realR))
}
real/real.go
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)
}
result, err := httputil.DumpResponse(resp, true)
resp.Body.Close()
if err != nil {
panic(err)
}
return string(result)
}
mock/mockretriever.go
package mock
type Retriever struct {
Contents string
}
func (r Retriever) Get(url string) string {
return r.Contents
}
接口的值类型
main.go
package main
import (
"ZipTest_backend/mock"
"ZipTest_backend/real"
"fmt"
"time"
)
type Retriever interface {
Get(string) string
}
func download(r Retriever) string {
return r.Get("http://www.imooc.com")
}
func inspect(r Retriever) {
fmt.Printf("%T %v\n", r, r)
fmt.Println("Type Switch : ")
switch v := r.(type) {
case mock.Retriever:
fmt.Println("Contents : ", v.Contents)
case *real.Retriever:
fmt.Println("UserAgent : ", v.UserAgent)
}
}
func main() {
var r Retriever
r = mock.Retriever{"this is a fake imooc.com"}
inspect(r)
// fmt.Println(download(r))
var realR Retriever = &real.Retriever{
UserAgent: "Mozilla/5.0",
TimeOut: time.Minute,
}
// fmt.Printf("%T %v\n", realR, realR)
inspect(realR)
realRetriever := realR.(*real.Retriever)
fmt.Println(realRetriever.TimeOut)
if mockRetriever, ok := realR.(mock.Retriever); ok {
fmt.Println(mockRetriever.Contents)
} else {
fmt.Println("not a mock retriever")
}
// fmt.Println(download(realR))
}
- 接口变量自带指针
- 接口变量同样采用值传递,几乎不需要使用接口的指针
- 指针接受者实现只能以指针方式使用;值接受者都可
- 便是任何类型:interface{}
- Type Assertion
- Type Switch