惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Stack Overflow Blog
Stack Overflow Blog
量子位
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
美团技术团队
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
Recent Announcements
Recent Announcements
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Security Blog
Microsoft Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
酷 壳 – CoolShell
酷 壳 – CoolShell
J
Java Code Geeks
V
V2EX
大猫的无限游戏
大猫的无限游戏
D
DataBreaches.Net
博客园 - Franky
爱范儿
爱范儿
T
Tailwind CSS Blog
A
About on SuperTechFans
Google DeepMind News
Google DeepMind News
博客园_首页
B
Blog RSS Feed
博客园 - 司徒正美
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

Mohuishou

如何实现支持多集群的 Kubernetes Operator? 第三方应用如何调用我们 kubebuilder 生成的自定义资源? Kubernetes 简明教程 k8s job 为何迟迟不能结束? Go 工程化(十一) 如何优雅的写出 repo 层代码 Go 工程化(十) 如何在整洁架构中使用事务? 给博客添加章节目录 使用 Notion Database 管理静态博客文章 一个普通 Go 开发的三年 4. localhost 就一定是 localhost 么? Go可用性(七) 总结: 一张图串联可用性知识点 Go可用性(六) 熔断 10. 总结 9. kubebuilder 进阶: 源码分析 8. kubebuilder 进阶: webhook 7. kubebuilder 进阶: 测试 6. kubebuilder 实战: status & event 5. kubebuilder 实战: CRUD 4. kustomize 简明教程 3. KubeBuilder 简明教程 2. Kind: 如何快速搭建本地 K8s 开发环境? 1. Operator概述: 如何对 Kubernetes 进行扩展 Go可用性(五) 自适应限流 Go可用性(四) 漏桶算法 Go可用性(三) 令牌桶的实现 rate/limt Go可用性(二) 令牌桶原理及使用 Go可用性(一) 隔离设计 Go并发编程(十二) Singleflight Go工程化(九) 项目重构实践 Go工程化(八) 单元测试
Go设计模式19-访问者模式
Mohuishou · 2020-10-18 · via Mohuishou

原课程中讲解访问者模式的时候用到了继承和函数重载这两个 Go 中没有的特性,接下来的呢,会通过继承实现。
注意由于没有函数重载,所以我们并不知道传递过来的对象是什么类型,这个时候只能采用类型断言的方式来对不同的类型做不同的操作,但是正式由于没有函数重载,所以其实完全可以不用访问者模式直接传入参数就好了。
以前我们经常说不要用写其他语言的方式来写 Go,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
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
package visitor

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestCompressor_Visit(t *testing.T) {
tests := []struct {
name string
path string
wantErr string
}{
{
name: "pdf",
path: "./xx.pdf",
},
{
name: "ppt",
path: "./xx.ppt",
},
{
name: "404",
path: "./xx.xx",
wantErr: "not found file type",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := NewResourceFile(tt.path)
if tt.wantErr != "" {
require.Error(t, err)
require.Contains(t, err.Error(), tt.wantErr)
return
}

require.NoError(t, err)
compressor := &Compressor{}
f.Accept(compressor)
})
}
}

// 不用 Accept 其实也是可以的
func TestCompressor_Visit2(t *testing.T) {
tests := []struct {
name string
path string
wantErr string
}{
{
name: "pdf",
path: "./xx.pdf",
},
{
name: "ppt",
path: "./xx.ppt",
},
{
name: "404",
path: "./xx.xx",
wantErr: "not found file type",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := NewResourceFile(tt.path)
if tt.wantErr != "" {
require.Error(t, err)
require.Contains(t, err.Error(), tt.wantErr)
return
}

require.NoError(t, err)
compressor := &Compressor{}
compressor.Visit(f)
})
}
}