main.go:
package main
import "fmt"
type Retriever interface {
Get(url 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"}
// 或者:r = &mock.Retriever{"this is a fake imooc.com"}
// 打印接口变量的类型和值
fmt.Printf("%T %v\n", r, r) // mock.Retriever {this is a fake imooc.com}
inspect(r) // Contents: this is a fake imooc.com
// 指针接收者只能以指针方式使用
r = &real.Retriever{
UserAgent: "Mozilla/5.0",
TimeOut: time.Minute,
}
// 打印接口变量的类型和值
fmt.Printf("%T %v\n", r, r) // *real.Retriever &{Mozilla/5.0 1m0s}
inspect(r) // UserAgent: Mozilla/5.0
// Type assertion:通过“接口变量.(type)”取得接口肚子里的类型
// (如r.(*real.Retriever)和r.(mock.Retriever))
if mockRetriever, ok := r.(mock.Retrivever); ok {
fmt.Println(mockRetriever.Contents)
} else {
fmt.Println("not a mock retriever") // not a mock retriever
}
}
func inspect(r Retriever) {
// Type switch
switch v := r.(type) {
case mock.Retriever:
fmt.Println("Contents:", v.Contents)
case *real.Retriever:
fmt.Println("UserAgent:", v.UserAgent)
}
}
mockretriever.go:
package mock
type Retriever struct {
Contents string
}
// 值接收者
func (r Retriever) Get(url string) string {
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 {
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)
}
接口变量(interface变量)肚子里有什么:
①以值方式使用
②以指针方式使用
☆因为接口变量自带指针,所以几乎不需要使用接口的指针
“interface{}”表示任何类型:
package queue
type Queue []interface{} // 让queue支持任何类型
func (q *Queue) Push(v int) { // 底层支持任何类型,上层只有int
*q = append(*q, v)
}
func (q *Queue) Pop() int { // 底层支持任何类型,上层只有int
head := (*q)[0]
*q = (*q)[1:]
return head.(int) // 强制类型转换
}
func (q *Queue) IsEmpty() bool {
return len(*q) == 0
}
package main
import (
"fmt"
".../queue"
)
func main() {
q := queue.Queue{1}
q.Push(2)
q.Push(3)
fmt.Println(q.Pop()) // 1
fmt.Println(q.Pop()) // 2
fmt.Println(q.IsEmpty()) // false
fmt.Println(q.Pop()) // 3
fmt.Println(q.IsEmpty()) // true
}