一、目录结构
mock
---mockretriever.go
real
---retriever.go
main.go
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, //实现了Poster,如果是指针传递则可以改变对象属性值
form map[string]string) string {
r.Contents = form["contents"]
return "ok"
}
func (r *Retriever) Get(url string) string {//实现了Retriever
return r.Contents
}
retriever.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 {//实现了Retriever
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)
}
main.go
package main
import (
"fmt"
"learn/retriever/mock"
"learn/retriever/real"
"time"
)
type Retriever interface {//接口定义
Get(url string) string
}
type Poster interface {//接口定义
Post(url string,
form map[string]string) string
}
const url = "http://www.baidu.com"
func download(r Retriever) string {//接口使用
return r.Get(url)
}
func post(poster Poster) {//接口使用
poster.Post(url,
map[string]string{
"name": "ccmouse",
"course": "golang",
})
}
type RetrieverPoster interface {//接口定义,里面有两个方法Get和Post
Retriever
Poster
}
func session(s RetrieverPoster) string {
s.Post(url, map[string]string{ //再调用Get和Post会向下转为mock.Retriever的指针,可以改变对象属性值
"contents": "another faked baidu.com",
})
return s.Get(url)
}
func main() {
var r Retriever//不用写成指针,接口没有指针的概念
mockRetriever := mock.Retriever{
Contents: "this is a fake baidu.com"}//向上转型为RetrieverPoster
r = &mockRetriever//向上转型Retriever
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))//指针传递,因为mock.Retriever类定义为指针传递,func (r *Retriever) String() string {}
}
func inspect(r Retriever) {
fmt.Println("Inspecting", r)
fmt.Printf(" > Type:%T Value:%v\n", r, r)//实现String接口,则调用实现的方法打印String
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()
}
输出结果:
Inspecting Retriever: {Contents=this is a fake baidu.com}
> Type:*mock.Retriever Value:Retriever: {Contents=this is a fake baidu.com}//实现了String接口,所以打印了我们自定义的
> Type switch: Contents: this is a fake baidu.com
Inspecting &{Mozilla/5.0 1m0s}
> Type:*real.Retriever Value:&{Mozilla/5.0 1m0s}
> Type switch: UserAgent: Mozilla/5.0
r is not a mock retriever
Try a session with mockRetriever
another faked baidu.com
go语言中实现接口,不要指定接口名,直接实现函数就好。如果想要对象属性,实现接口时,需要用指针传递。
接口本身没有指针的说法。