# Filter实现AOP
- 责任链是很常见的用于解决AOP的一种方式。
- 类似的也叫做middleware,interceptor... 本质是一样
- Go 函数是一等公民,所以可以考虑使用闭包来实现责任链
- filter 很常见,比如说鉴权,日志,tracing,以及跨域等都可以用filter来实现
package main
import (
"fmt"
"time"
)
type Filter func(c *Context)
type FilterBuilder func(next Filter) Filter
// 确保MetricFilterBuilder是一个FilterBuilder
var _ FilterBuilder = MetricFilterBuilder
func MetricFilterBuilder(next Filter) Filter {
return func (c *Context) {
startTime := time.Now()
next(c)
endTime := time.Now()
fmt.Printf("use time: %f \n", endTime.Sub(startTime).Seconds())
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Server修改
初始化Server时,允许使用builders并将根节点保存,后续使用
func NewServer(name string, builders... FilterBuilder) Server {
handler := NewHandlerBaseOnMap()
var root Filter = func(c *Context) {
handler.ServeHTTP(c.W, c.R)
}
for i:=len(builders)-1; i>=0; i-- {
b := builders[i]
root = b(root)
}
return &SDKHTTPServer{
Name: name,
handler: handler,
root: root,
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
修改Start函数
func (S *SDKHTTPServer) Start(port string) error {
// 由 http.Handle() 改为 HandleFunc 则 handle可以不实现ServeHTTP接口
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
S.root(NewContext(w, r))
})
return http.ListenAndServe(port, nil)
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 接口优化
我们看到我们使用Start函数中,在使用root,我们使用NewContext生成了新的Context,但是在NewServer中我又将 Context 拆开了。
func (S *SDKHTTPServer) Start(port string) error {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
S.root(NewContext(w, r)) // 生成了Context
})
return http.ListenAndServe(port, nil)
}
1
2
3
4
5
6
2
3
4
5
6
NewServer:
func NewServer(name string, builders... FilterBuilder) Server {
...
var root Filter = func(c *Context) {
handler.ServeHTTP(c.W, c.R) // 又将Context拆开了,
}
...
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 修改handler
接口修改:
type Handler interface {
ServeHTTP(ctx *Context) // 直接使用Context
RouteAble
}
1
2
3
4
2
3
4
实现也修改:
func (h *HandlerBaseOnMap) ServeHTTP(ctx *Context) {
request := ctx.R
key := h.key(request.Method, request.URL.Path)
if handler, ok := h.handlers[key]; ok {
handler(ctx)
} else {
_ = ctx.WriteJSON(http.StatusNotFound, "Not Found")
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# Server修改
func NewServer(name string, builders... FilterBuilder) Server {
handler := NewHandlerBaseOnMap()
var root Filter = handler.ServeHTTP
for i:=len(builders)-1; i>=0; i-- {
b := builders[i]
root = b(root)
}
return &SDKHTTPServer{
Name: name,
handler: handler,
root: root,
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 拓展拦截器(中间件)实现
在 Golang 中,拦截器模式(Interceptor Pattern)是一种常见的设计模式,用于在不修改现有代码的情况下增加或修改功能。它通过使用接口(interface)和包装器(wrapper)的方式来实现。
在拦截器模式中,我们通过实现一个接口,然后用一个包装器结构来封装原始对象,从而在调用原始对象的方法之前或之后执行特定的操作。
# 接口实现
// 定义一个接口,包含原始对象的方法
type UserService interface {
GetUserByID(id int) (User, error)
}
// 原始对象,实现 UserService 接口
type UserServiceImpl struct{}
func (s *UserServiceImpl) GetUserByID(id int) (User, error) {
// 实际的业务逻辑在这里
// ...
}
// 包装器结构,用于拦截原始对象的方法调用并执行附加操作
type LoggingInterceptor struct {
userService UserService
}
func (li *LoggingInterceptor) GetUserByID(id int) (User, error) {
// 在调用原始方法之前执行的操作
fmt.Println("Calling GetUserByID with ID:", id)
// 调用原始方法
user, err := li.userService.GetUserByID(id)
// 在调用原始方法之后执行的操作
if err == nil {
fmt.Println("GetUserByID succeeded")
} else {
fmt.Println("GetUserByID failed with error:", err)
}
return user, err
}
// 使用 LoggingInterceptor 封装 UserServiceImpl
func NewLoggingInterceptor(userService UserService) UserService {
return &LoggingInterceptor{userService: userService}
}
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
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
# 闭包实现
// 原始对象的函数定义
type GetUserByIDFunc func(id int) (User, error)
// 原始对象的实现
func (fn GetUserByIDFunc) GetUserByID(id int) (User, error) {
return fn(id)
}
// 包装器函数,用于拦截原始函数调用并执行附加操作
func LoggingInterceptor(getUserByID GetUserByIDFunc) GetUserByIDFunc {
return func(id int) (User, error) {
// 在调用原始函数之前执行的操作
fmt.Println("Calling GetUserByID with ID:", id)
// 调用原始函数
user, err := getUserByID(id)
// 在调用原始函数之后执行的操作
if err == nil {
fmt.Println("GetUserByID succeeded")
} else {
fmt.Println("GetUserByID failed with error:", err)
}
return user, err
}
}
// 使用 LoggingInterceptor 封装原始函数
userServiceImpl := &UserServiceImpl{}
getUserByIDWithLogging := LoggingInterceptor(userServiceImpl.GetUserByID)
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
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
# 闭包加接口实现
package __extend_Interceptor
import (
"fmt"
"time"
)
type FilterService interface {
Serve(name string)
}
type MyFilter struct {
}
type FilterServiceBuilder func(next FilterService) FilterService
func (f *MyFilter)Serve(name string) {
fmt.Printf("MyFilter Serve: %s \n", name)
}
type InterceptorFilter struct {
next FilterService
}
func (f *InterceptorFilter) Serve(name string) {
fmt.Printf("InterceptorFilter Serve Start \n")
f.next.Serve(name)
fmt.Printf("InterceptorFilter Serve End \n")
}
func NewInterceptorFilter(next FilterService) FilterService {
return &InterceptorFilter{
next: next,
}
}
type MetricFilter struct {
next FilterService
}
func (f *MetricFilter) Serve(name string) {
startTime := time.Now()
f.next.Serve(name)
endTime := time.Now()
fmt.Printf("MetricFilter use time: %f \n", endTime.Sub(startTime).Seconds())
}
func NewMetricFilter(next FilterService) FilterService {
return &MetricFilter{
next: next,
}
}
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
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
测试调试代码:
package __extend_Interceptor
import "testing"
func TestInterceptor(t *testing.T) {
r := NewFilterRoot(&MyFilter{}, NewMetricFilter, NewInterceptorFilter)
r.Serve("hello")
}
//=== RUN TestInterceptor
//InterceptorFilter Serve Start
//MyFilter Serve: hello
//InterceptorFilter Serve End
//MetricFilter use time: 0.000065
//--- PASS: TestInterceptor (0.00s)
//PASS
type FilterRoot struct {
root FilterService
}
func (f *FilterRoot)Serve(name string) {
f.root.Serve(name)
}
func NewFilterRoot(root FilterService, filterServiceBuilders... FilterServiceBuilder) FilterRoot {
for i:=len(filterServiceBuilders)-1; i>=0; i-- {
f := filterServiceBuilders[i]
root = f(root)
}
return FilterRoot{
root: root,
}
}
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
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
# 接口加生命周期
package __extend_Interceptor
import "fmt"
// 定义一个接口,包含原始对象的方法以及生命周期函数
type UserService interface {
// 原始对象的方法
GetUserByID(id int) string
// 生命周期函数
Setup()
Teardown()
}
// 原始对象,实现 UserService 接口
type UserServiceImpl struct{}
func (s *UserServiceImpl) GetUserByID(id int) string {
// 实际的业务逻辑在这里
// ...
return "李四"
}
func (s *UserServiceImpl) Setup() {
// 在调用原始方法之前执行的操作
fmt.Println("UserService setup")
}
func (s *UserServiceImpl) Teardown() {
// 在调用原始方法之后执行的操作
fmt.Println("UserService teardown")
}
// 包装器结构,用于拦截原始对象的方法调用并执行附加操作
type LoggingInterceptor struct {
userService UserService
}
func (li *LoggingInterceptor) GetUserByID(id int) string {
// 在调用原始方法之前执行的操作
fmt.Println("Calling GetUserByID with ID:", id)
// 在调用原始方法之前执行生命周期函数
li.userService.Setup()
// 调用原始方法
name := li.userService.GetUserByID(id)
fmt.Println(name)
// 在调用原始方法之后执行生命周期函数
li.userService.Teardown()
return name
}
func (li *LoggingInterceptor) Teardown() {
}
func (li *LoggingInterceptor) Setup() {
}
// 使用 LoggingInterceptor 封装 UserServiceImpl
func NewLoggingInterceptor(userService UserService) UserService {
return &LoggingInterceptor{userService: userService}
}
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
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
测试调试代码
package __extend_Interceptor
import "testing"
func TestLifeHock(t *testing.T) {
l := NewLoggingInterceptor(&UserServiceImpl{})
l.GetUserByID(1)
}
//=== RUN TestLifeHock
//Calling GetUserByID with ID: 1
//UserService setup
//李四
//UserService teardown
//--- PASS: TestLifeHock (0.00s)
//PASS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
← Handler抽象 Handler路由树 →