main.go:
package mainimport "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 switchswitch 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
}
