整洁架构项目的随手整理

viper库的使用

在阅读https://github.com/bxcodec/go-clean-arch时,发现了viper库,这是一个加载配置时使用的库,可以避免定义struct

errgroup

下面这块的写法可以学习下,来自https://github.com/bxcodec/go-clean-arch/blob/master/article/usecase/article_ucase.go

这个函数实现的功能就是根据data里数组的各个ID,查询其具体内容

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
func (a *articleUsecase) fillAuthorDetails(c context.Context, data []domain.Article) ([]domain.Article, error) {
g, ctx := errgroup.WithContext(c) // 当某个goroutine出错后或者传入的c超时了,返回的ctx会被cancel掉

// Get the author's id
mapAuthors := map[int64]domain.Author{}

for _, article := range data { //nolint
mapAuthors[article.Author.ID] = domain.Author{}
}
// Using goroutine to fetch the author's detail
chanAuthor := make(chan domain.Author) // channel初始化后可以无线接收
for authorID := range mapAuthors {
authorID := authorID
g.Go(func() error { // g.Go开启goroutine
res, err := a.authorRepo.GetByID(ctx, authorID)
if err != nil {
return err
}
chanAuthor <- res
return nil
})
}

go func() {
err := g.Wait() // 等待所有查询goroutine执行完毕,查询goroutine并行可以提高速度
if err != nil {
logrus.Error(err)
return
}
close(chanAuthor) // 一定要关闭
}()

for author := range chanAuthor {
if author != (domain.Author{}) {
mapAuthors[author.ID] = author
}
}

if err := g.Wait(); err != nil {
return nil, err
}

// merge the author's data
for index, item := range data { //nolint
if a, ok := mapAuthors[item.Author.ID]; ok {
data[index].Author = a
}
}
return data, nil
}

数据库抽象

总结起来就是数据库的操作需要抽象成interface,对外提供方法供API端调用

名字可以参考定义为XXXUsecase,XXX就是关联的数据库模型,比如对文章的操作就是articleUsecase

启动文件位置

启动的main.go可以放到单独的目录,比如app目录


整洁架构项目的随手整理
https://nrbackback.github.io/2023/02/01/整洁架构项目的随手整理/
作者
John Doe
发布于
2023年2月1日
许可协议