main.go:

    1. package main
    2. import "fmt"
    3. type Retriever interface {
    4. Get(url string) string
    5. }
    6. func download(r Retriever) string {
    7. return r.Get("http://www.imooc.com")
    8. }
    9. func main() {
    10. var r Retriever
    11. // 值接收者可以以值方式使用,也可以以指针方式使用
    12. r = mock.Retriever{"this is a fake imooc.com"}
    13. // 或者:r = &mock.Retriever{"this is a fake imooc.com"}
    14. // 打印接口变量的类型和值
    15. fmt.Printf("%T %v\n", r, r) // mock.Retriever {this is a fake imooc.com}
    16. inspect(r) // Contents: this is a fake imooc.com
    17. // 指针接收者只能以指针方式使用
    18. r = &real.Retriever{
    19. UserAgent: "Mozilla/5.0",
    20. TimeOut: time.Minute,
    21. }
    22. // 打印接口变量的类型和值
    23. fmt.Printf("%T %v\n", r, r) // *real.Retriever &{Mozilla/5.0 1m0s}
    24. inspect(r) // UserAgent: Mozilla/5.0
    25. // Type assertion:通过“接口变量.(type)”取得接口肚子里的类型
    26. // (如r.(*real.Retriever)和r.(mock.Retriever))
    27. if mockRetriever, ok := r.(mock.Retrivever); ok {
    28. fmt.Println(mockRetriever.Contents)
    29. } else {
    30. fmt.Println("not a mock retriever") // not a mock retriever
    31. }
    32. }
    33. func inspect(r Retriever) {
    34. // Type switch
    35. switch v := r.(type) {
    36. case mock.Retriever:
    37. fmt.Println("Contents:", v.Contents)
    38. case *real.Retriever:
    39. fmt.Println("UserAgent:", v.UserAgent)
    40. }
    41. }

    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变量)肚子里有什么:
    ①以值方式使用
    image.png
    ②以指针方式使用
    image.png
    ☆因为接口变量自带指针,所以几乎不需要使用接口的指针

    “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
    }