一. duck typing 鸭子类型
Go语言的鸭子类型
- 同时具有python, c++的duck typing 的灵活性
def download(Retriver):
return Retriver.get("www.gihub.com")
- 又有java的类型检查
<R extends Retriver>
String download(R r) {
return r.get("www.github.com")
}
二. 接口的定义和实现
接口的定义
使用者download
实现者retriever
- 接口由使用者定义
type Retriever interface {
Get(source string) string
}
func download(retriever Retriever) string {
return retriever.Get("www.github.com")
}
接口的实现
- 接口实现是隐式的
- 只要实现接口里的方法
三. 接口的组合
- 可以将多个接口组合起来
type Retriever interface {
Get(url string) string //不需要func关键字
}
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": "another faked imooc.com",
})
return s.Get(url)
}
代码实例
- 目录
├── main.go
├── mock
│ └── mockretriever.go
└── real
└── retriever.go
- main.go
package main
import (
"fmt"
"time"
"learngo/lang/retriever/mock"
"learngo/lang/retriever/real"
)
type Retriever interface {
Get(url string) string //不需要func关键字
}
type Poster interface {
Post(url string,
form map[string]string) string
}
const url = "http://www.imooc.com"
func download(r Retriever) string {
return r.Get(url)
}
func post(poster Poster) {
poster.Post(url,
map[string]string{
"name": "cannon",
"course": "golang",
})
}
type RetrieverPoster interface { // 接口组合
Retriever
Poster
}
func session(s RetrieverPoster) string { // 接口组合 可以调用每个接口的方法
s.Post(url, map[string]string{
"contents": "another faked imooc.com",
})
return s.Get(url)
}
func main() {
var r Retriever
mockRetriever := mock.Retriever{
Contents: "this is a fake imooc.com"}
r = &mockRetriever
inspect(r)
r = &real.Retriever{
UserAgent: "Mozilla/5.0",
TimeOut: time.Minute,
}
inspect(r)
// Type assertion
if mockRetriever, ok := r.(*mock.Retriever); ok {
fmt.Println(mockRetriever.Contents)
} else {
fmt.Println("r is not a mock retriever")
}
fmt.Println(
"Try a session with mockRetriever")
fmt.Println(session(&mockRetriever))
}
func inspect(r Retriever) {
fmt.Println("Inspecting", r)
fmt.Printf(" > Type:%T Value:%v\n", r, r)
fmt.Print(" > Type switch: ")
switch v := r.(type) {
case *mock.Retriever:
fmt.Println("Contents:", v.Contents)
case *real.Retriever:
fmt.Println("UserAgent:", v.UserAgent)
}
fmt.Println()
}
- retirever.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)
}
- mockretriever.go
package mock
import "fmt"
type Retriever struct {
Contents string
}
func (r *Retriever) String() string { // 系统接口String
return fmt.Sprintf(
"Retriever: {Contents=%s}", r.Contents)
}
func (r *Retriever) Post(url string,
form map[string]string) string {
r.Contents = form["contents"]
return "ok"
}
func (r *Retriever) Get(url string) string {
return r.Contents
}
四. 常用系统接口
- Stringer
- Reader/Writer