go的类型及接口实现

go结构化类型系统,类似与duck typing

go语言是编译时就会绑定的,从动态绑定的角度,不是duck typing

具有c++、python的灵活性,实现对应的方法就可以运行,又想要java的类型检查

go的接口实现是隐式的,只要实现接口里的方法就可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

// /type_interface/mock/Retriever.go
package mock
type Retriever1 struct {
Contents string
}

func (r Retriever1) Get(str string) string{
return r.Contents
}


// /type_interface/real/Retriever.go
package real
import (
"net/http"
"net/http/httputil"
"time"
)

type Retriever2 struct {
UserAgent string
TimeOut time.Duration
}

func (r *Retriever2) 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)
}

接口变量里有什么

  1. 实现者的类型
  2. 实现者的指针(实现者的值)

接口变量的特点

  • 接口变量里面自带指针
  • 接口变量同样采用值传递,几乎不需要使用接口的指针
  • 指针接受者实现只能以指针方式使用,而值接受者两种都可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// /type_interface/main.go
package main

import (
"fmt"
"type_interface/mock"
real2 "type_interface/real"
)

type Retriever3 interface {
Get(url string) string
}

func download(r Retriever3) string {
return r.Get("http://www.baidu.com")
}


func inspect(r Retriever3) {
//
switch v := r.(type) {
case mock.Retriever1:
fmt.Println("mock.Retriever1: ", v.Contents)
case *real2.Retriever2:
fmt.Println("*real2.Retriever2: ", v.UserAgent)
}
}

func main() {
// 声明一个接口变量
var r Retriever3

// 使用mock.Retriever1来定义这个接口变量
r = mock.Retriever1{Contents: "this is faker, you know?"} // 值类型还是指针都可
inspect(r)

// 使用real2.Retriever2来定义这个接口变量
r = &real2.Retriever2{ //必须为指针类型
UserAgent: "chrome 19.0",
TimeOut: time.Minute,
}
inspect(r)

//fmt.Println(download(r))

// 类型断言
realRetriever := r.(*real2.Retriever2)
fmt.Println(realRetriever.TimeOut)

// 类型断言可能会失败,失败ok为false
if mockRetriever, ok := r.(mock.Retriever1); ok {
fmt.Println(mockRetriever.Contents)
} else {
fmt.Printf("r is not a mockRetriever")
}

}

查看接口变量

  1. 表示任何变量: interface{}
  2. Type Assertion
  3. Type Switch

接口的组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

// /type_interface/mock/Retriever.go
package mock

type Retriever1 struct {
Contents string
}

// 实现系统中的接口 ctrl + enter 可以显示针对类型的实现下拉
func (r *Retriever1) String() string {
return fmt.Sprintf("实现的string方法返回的内容是 Retriever1: {Contents=%s} ", r.Contents)
}


func (r *Retriever1) Post(url string, form map[string]string) string {
r.Contents = form["contents"]
return "ok"
}

func (r *Retriever1) Get(str string) string {
return r.Contents
}



// /type_interface/main.go
type Retriever3 interface {
Get(url string) string
}

type Poster interface {
Post(url string, form map[string]string) string
}

type RetrieverPoster interface {
Retriever3
Poster
}

func session(s RetrieverPoster) string {
s.Post(url, map[string]string{
"name": "edit",
"contents": "faker is here right",
})
return s.Get(url)
}

func printFlie(filename string) {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}

func main(){
var r Retriever3
r = &mock.Retriever1{Contents: "this is faker, you know?"}

fmt.Printf(session(r.(*mock.Retriever1))) // faker is here right

fmt.Println(r) // 实现的string方法返回的内容是 Retriever1: {Contents=this is faker, you know?}
}