Go语言学习笔记6-接口

接口

接口本事是调用方和是实现方均需要遵守的一种协议,大家按照统一的方法命名参数类型和数量来协调逻辑处理的过程
实现接口需遵循的条件:

  • 接口的方法与实现接口的类型方法格式必须一致
  • 接口中的所有方法均要被实现

type 接口类型名 interface {
方法名1(参数列表1) 返回值列表1
方法名2(参数列表2) 返回值列表2
}

  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
package main

import "fmt"

func main() {
var s Service = new(GameService)
s.Start()
s.Log("日志")
}

//定义接口
type Service interface {
Start()
Log(string)
}

type logger struct {
}

//内嵌结构体实现接口Log
func (g logger) Log(l string) {
fmt.Println(l)
}

type GameService struct {
logger
}

//实现接口Start
func (g GameService) Start() {
fmt.Println("start")
}

  1. 接口与接口间可以通过嵌套创造出新的接口
  2. 使用接口断言将接口转换成另外一个接口,也可以将接口转换成另外的类型
    t := i.(T)
    • i:接口变量
    • T:转换的目标类型
    • t:转换后的变量
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
package main

import "fmt"

type Flyer interface {
Fly()
}

type Walker interface {
Walk()
}

type Bird struct {
}

type Pig struct {
}

func (p *Pig) Walk() {
fmt.Println("walk")
}

func (b *Bird) Walk() {
fmt.Println("bird:walk")
}

func (b *Bird) Fly() {
fmt.Println("bird:flyer")
}

func main() {
animals := map[string] interface{}{
"bird": new(Bird),
"pig": new(Pig),
}

for name, obj := range animals {
f, isFlyer := obj.(Flyer)
w, isWalker := obj.(Walker)

fmt.Printf("name:%s, isFlyaer:%v, isWalker:%v\n", name, isFlyer, isWalker)

if isFlyer {
f.Fly()
}

if isWalker {
w.Walk()
}
}
}
  1. 空接口是接口类型的特殊形式,空接口没有任何方法,因此任何类型都无须实现接口。因此空接口类型可以保存任何值,类型C#中的Object
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
package main

import "fmt"

//使用空接口实现可以保存任何值的字典
type Dictionary struct {
data map[interface{}] interface{}
}

func (d *Dictionary) Get(key interface{}) interface{} {
return d.data[key]
}

func (d *Dictionary) Set(key interface{}, value interface{}) {
d.data[key] = value
}

func (d *Dictionary) Visit(callback func(k, v interface{}) bool) {
if callback == nil {
return
}

for k, v := range d.data {
if !callback(k, v) {
return
}
}
}

func (d *Dictionary) Clear() {
d.data = make(map[interface{}] interface{})
}

func NewDictionary() *Dictionary {
d := &Dictionary{}

d.Clear()
return d
}

func main() {
dict := NewDictionary()

dict.Set("My Factory", 60)
dict.Set("Terra Craft", 36)
dict.Set("Don't Hungry", 24)

favorite := dict.Get("Terra Craft")
fmt.Println(favorite)

dict.Visit(func(k, v interface{}) bool {
if v.(int) > 40 {
fmt.Println(k, "is expensive")
return true
}

fmt.Println(k, "is cheap")
return true
})
}
  1. 使用switch可以判断一个接口内保存或实现的类型

switch 接口变量.(type) {
case 类型1:
//变量是类型1时的处理
case 类型2:
//变量是类型2时的处理
default:
//变量不是所有case中列举的类型时的处理
}

  1. 实现有限状态机
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
package main

import (
"errors"
"fmt"
"reflect"
)

//状态接口
type State interface {
Name() string
EnableSameTransit() bool
OnBegin()
OnEnd()
CanTransitTo(name string) bool
}

//从状态实例获取状态名
func StateName(s State) string {
if s == nil {
return "none"
}

return reflect.TypeOf(s).Elem().Name()
}

//状态的基础信息和默认实现
type StateInfo struct {
name string
}

//状态名
func (s *StateInfo) Name() string {
return s.name
}

//提供给内部设置名字
func (s *StateInfo) setName(name string) {
s.name = name
}

//允许同状态转移
func (s *StateInfo) EnableSameTransit() bool {
return false
}

//默认将状态开启时实现
func (s *StateInfo) OnBegin() {

}

//默认将状态结束时实现
func (s *StateInfo) OnEnd() {

}

//默认可以转移到任何状态
func (s *StateInfo) CanTransitTo(name string) bool {
return true
}

//状态管理器
type StateManager struct {
stateByName map[string]State //已添加的状态
onChange func(from, to State) //状态改变时的回调
cur State //当前状态
}

//根据名字获取指定状态
func (sm *StateManager) Get(name string) State {
if v, ok := sm.stateByName[name]; ok {
return v
}

return nil
}

//添加一个状态到管理器中
func (sm *StateManager) Add(s State) {
name := StateName(s)

//将s装换为能设置名字的接口,然后调用该接口
s.(interface{
setName(name string)
}).setName(name)

//根据状态名获取已经添加的状态,检查改状态是否存在
if sm.Get(name) != nil {
panic("duplicate state:" + name)
}

//根据名字保存到map中
sm.stateByName[name] = s
}

//初始化状态管理器
func NewStateManager() *StateManager {
return &StateManager{
stateByName: make(map[string]State),
}
}

//定义错误
var ErrStateNotFound = errors.New("state not found")
var ErrForbidSameStateTransit = errors.New("forbid same state transit")
var ErrCannotTransitToState = errors.New("cannot transit to state")

func (sm *StateManager) CurrState() State {
return sm.cur
}

func (sm *StateManager) CanCurrTransitTo(name string) bool {
if sm.cur == nil {
return true
}

if sm.cur.Name() == name && !sm.cur.EnableSameTransit() {
return false
}

return sm.cur.CanTransitTo(name)
}

//转移到指定状态
func (sm *StateManager) Transit(name string) error {
//获取目标
next := sm.Get(name)

//目标不存在
if next == nil {
return ErrStateNotFound
}

//记录转移前的状态
pre := sm.cur

//当前有状态
if sm.cur != nil {
//相同的状态不用转换
if sm.cur.Name() == name && !sm.cur.EnableSameTransit() {
return ErrForbidSameStateTransit
}

//不能转移到目标状态
if !sm.cur.CanTransitTo(name) {
return ErrCannotTransitToState
}

//结束当前状态
sm.cur.OnEnd()
}

//将当前状态切换为要转移到的目标状态
sm.cur = next
//调用新状态的开始
sm.cur.OnBegin()

//通知回调
if sm.onChange != nil {
sm.onChange(pre, sm.cur)
}

return nil
}

//闲置状态
type IdleState struct {
StateInfo
}

func (i *IdleState) OnBegin() {
fmt.Println("idleState begin")
}

func (i *IdleState) OnEnd() {
fmt.Println("idleState end")
}

//移动状态
type MoveState struct {
StateInfo
}

func (m *MoveState) OnBegin() {
fmt.Println("moveState begin")
}

func (m *MoveState) OnEnd() {
fmt.Println("moveState end")
}

func (m *MoveState) EnableSameTransit() bool {
return true
}

//跳跃状态
type JumpState struct {
StateInfo
}

func (j *JumpState) OnBegin() {
fmt.Println("jumpState begin")
}

func (j *JumpState) CanTransitTo(name string) bool {
return name != "MoveState"
}

func main() {
sm := NewStateManager()

//响应状态转移的通知
sm.onChange = func(from, to State) {
fmt.Printf("%s--> %s\n\n", StateName(from), StateName(to))
}

//添加3个状态
sm.Add(new(IdleState))
sm.Add(new(MoveState))
sm.Add(new(JumpState))

//在不同状态间转移
transitAndReport(sm, "IdleState")
transitAndReport(sm, "MoveState")
transitAndReport(sm, "MoveState")
transitAndReport(sm, "JumpState")
transitAndReport(sm, "JumpState")
transitAndReport(sm, "IdleState")
}

//封装转移状态和输出日志
func transitAndReport(sm *StateManager, target string) {
if err := sm.Transit(target); err != nil {
fmt.Printf("Failed! %s-->%s, %s\n\n", sm.CurrState().Name(), target, err.Error())
}
}
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2021 Azella
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信