项目布局
最后更新于:2022-04-02 02:35:54
[TOC]
## 参考bilibili
```
.
├── app
│ ├── admin
│ │ └── foo/../
│ │ ├── cmd
│ │ │ └── main.go
│ │ ├── configs
│ │ │ ├── http.conf
│ │ │ ├── memcache.conf
│ │ │ ├── mysql.con
│ │ │ └── redis.con
│ │ ├── internal
│ │ │ ├── dao
│ │ │ │ ├── dao.go
│ │ │ │ └── user.go
│ │ │ ├── model
│ │ │ ├── server
│ │ │ │ └── http
│ │ │ │ └── router.go
│ │ │ │ └── user.go
│ │ │ └── service
│ │ └── api
│ │ └── api.proto
│ ├── job
│ │ └── foo/../
│ │ ├── cmd
│ │ │ └── main.go
│ │ ├── configs
│ │ │ ├── http.conf
│ │ │ ├── memcache.conf
│ │ │ ├── mysql.con
│ │ │ └── redis.con
│ │ ├── internal
│ │ │ ├── dao
│ │ │ ├── model
│ │ │ ├── server
│ │ │ │ └── http
│ │ │ └── service
│ │ └── api
│ │ └── api.proto
│ ├── common
│ └── service
├── library
│ ├── cache
│ │ ├── cache
│ │ └── memcache
│ ├── conf
│ ├── container
│ ├── database
│ │ ├── orm
│ │ ├── sql
│ │ └── tidb
│ ├── ecode
│ │ └── pd
│ ├── log
│ ├── net
│ │ ├── http
│ │ ├── rpc
│ │ └── strace
│ └── text
│ └── translate
└── buid
└── root.sh
```
## 要点
1. library 是对第三方库的封装,或自己实现的基础库
2. app 中的调用的库尽量引用 library 中,而非外部库
3. app中的模块,可根据实际模块大小,来进行拆封到更细
4. 用gorm等工具并且不考虑数据库兼容问题时,推荐还是用原生sql,且只获取想要字段,并在 model 目录做结构体映射
## 模块讲解
### 对 foo 模块详解
#### dao
dao 模块用来管理数据层的服务
如
dao.go在
```
type Dao struct {
db *sql.DB
redis *redis.Pool
redisExpire int32
mc *memcache.Pool
mcExpire int32
}
```
user.go 对 sql的具体操作
```
const (
_loadNotify = "SELECT n.id,topic.cluster,topic.topic,a.group,n.callback,n.concurrent,n.filter,n.mtime FROM notify AS n LEFT JOIN auth2 as a ON a.id=n.gid LEFT JOIN topic ON a.topic_id=topic.id WHERE n.state=1 AND n.zone=?"
)
// LoadNotify load all notify config.
func (d *Dao) LoadNotify(c context.Context, zone string) (ns []*model.Watcher, err error) {
rows, err := d.db.Query(c, _loadNotify, zone)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
n := new(model.Watcher)
if err = rows.Scan(&n.ID, &n.Cluster, &n.Topic, &n.Group, &n.Callback, &n.Concurrent, &n.Filter, &n.Mtime); err != nil {
return
}
ns = append(ns, n)
}
return
}
```
#### model
存放 dao 中获取到的model
```
type Watcher struct {
ID int64
Cluster string
Topic string
Group string
Offset string
Callback string
Filter bool
Concurrent int // concurrent goroutine for sub.
}
```
#### http
http 用来存放与http 相关的服务
1. http 的路由,及handle
2. handle的具体内部实现放在 service 中
router.php
```
...
project := version.Group("/projects")
{
project.GET("/favorite", favoriteProjects)
project.POST("/favorite/edit", editFavorite)
project.GET("/common", queryCommonProjects)
}
...
```
project.go
```
...
func favoriteProjects(ctx *bm.Context) {
var (
req = &model.Pagination{}
err error
userName string
)
if err = ctx.Bind(req); err != nil {
ctx.JSON(nil, err)
return
}
if userName, err = getUsername(ctx); err != nil {
ctx.JSON(nil, err)
return
}
// 最终的生成在 service 处理
ctx.JSON(srv.FavoriteProjects(ctx, req, userName))
}
...
```
service/foo.go
```
...
func (s *Service) FavoriteProjects(c context.Context, req *model.Pagination, userName string) (resp *model.FavoriteProjectsResp, err error) {
// code
}
...
```
#### service
1. 把所有的服务都挂载 service 中
2. 对 handle 的具体实现放入service 中
```
type Service struct {
c *conf.Config
dao *dao.Dao
transferChan *fanout.Fanout
cron *cron.Cron
}
```
## 可以使用
';