作者 唐旭辉
## 目录
* [代码声明](#代码声明)
* [命名规范](#命名规范)
* [项目约定](#项目约定)
* [注意事项](#注意事项)
### 代码声明
#### 命名规范
1.包名
```
*
package名和目录保持一致,需避免和标准库冲突
小写
*
package comm
```
2.命名
```
package pkg
*1.错误*
/*
定义在包的首部,所有错误都定义在一起,
并且以Err开头
*/
var ErrFooBar = fmt.Errorf("pkg: ...")
*2.变量*
/*
采用驼峰命名
*/
var fooBar int
*3.常量*
/*
大写+下划线
*/
var(
FOO = 1
BAR = 2
FOO_BAR = 3
)
*4.结构*
/*
采用驼峰命名法
*/
type FooBar struct{
foo int
Bar string
}
*5.方法接口*
/*
采用驼峰命名法
非对外方法,首字母需为小写
*/
func foo(){}
func Foo(){}
```
3.目录结构
```
* conf //配置
* dev.conf
* prod.conf
* controller //控制器
* v1
* auth.go
* internal
* repository //存储层
* user.go
* *_mock.go
* model //模型
* protocol //协议层
* routers //路由
* service //逻辑层
* auth
* static //静态数据
* views //视图
* main.go
* Dockerfile
* README.md
* *.sh //脚本
```
#### 项目约定
1. 入参跟返回值都要定义一个协议结构 protocol.XxxRequest *protocol.XxxResponse,方便扩展
2. 函数方法的变量都定义在函数的头几行 var( ... )
3. 服务调用尽量封装成接口,方便测试扩展 比如:ISmsServe{ Send() error }
4. 公用的基础代码库,需要做一下封装放在 [gocomm](http://gitlab.fjmaimaimai.com/mmm-go/gocomm) ,方便在其他项目中调用
4. 可以使用代码生成固定格式, [项目地址](http://gitlab.fjmaimaimai.com/mmm-go/gencode) 脚本:.\gencode.exe new -c Auth -m Login
```
package pkg
//Login
func(this *AuthController)Login(){
var msg *mybeego.Message
defer func(){
this.Resp(msg)
}()
var request *protocol.LoginRequest
if err:=json.Unmarshal(this.ByteBody,&request);err!=nil{
log.Error(err)
msg = mybeego.NewMessage(1)
return
}
if b,m :=this.Valid(request);!b{
msg = m
return
}
msg = this.GenMessage(auth.Login(request))
}
/*Login */
type LoginRequest struct {
Xxx string`json:"xxx" valid:"Required"`
}
type LoginResponse struct {
}
func Login(request *protocol.LoginRequest)(rsp *protocol.LoginResponse,err error){
var (
)
rsp =&protocol.LoginResponse{}
return
}
```
#### 注意事项
1. 启动一个groutine(eg:go func(){}()),需要在函数内进行recover,不然groutine里面panic,会导致外部程序一起崩溃掉;
2. 当接受者是map, chan, func, 不要使用指针传递,因为它们本身就是引用类型
3. 当接受者类型是一个结构体并且很庞大,或者是一个大数组,建议使用指针传递来提高性能,其他场景使用值传递即可
4. 当接受者是一个结构体,并且包含了sync.Mutex或者类似的用于同步的成员。必须使用指针传递,避免成员拷贝
5. 当函数内部需要修改接受者,必须使用指针传递
6. 声明空的slice应该使用下面的格式: var t []string 不要使用 t := []string{} ,前者声明了一个nil slice而后者是一个长度为0的非nil的slice。
... ...
#!/bin/bash
pwd=`pwd`
target=`basename $pwd`
# Kill running program
pid=`ps -C ${target} -o pid=`
if [ -n "$pid" ]; then
echo "Stopping old version, PID: ${pid}"
if [ "$1" = "-f" ]; then
# force shutdown
echo "Force shutdown..."
kill $(ps -C ${target} -o pid=)
else
kill -s 2 $(ps -C ${target} -o pid=)
fi
# wait for program to stop
pid=`ps -C ${target} -o pid=`
while [ -n "$pid" ]; do
sleep 1
done
fi
# Rollback
if [ -f "${target}-backup" ]; then
echo "Rolling back..."
if [ -f "${target}" ]; then
rm "${target}"
fi
mv ${target}-backup ${target}
echo "Rollback Complete"
fi
# run
echo "Starting..."
./run.sh ${target}
echo "Done"
\ No newline at end of file
... ...
#!/bin/bash
echo "begin run $1"
# 以后台方式启动程序,并且将日志记录到 app.log
./$1 >> tmp.log 2>&1 &
pid=`ps -C $1 -o pid=`
if [ -n "$pid" ]; then
echo "success"
else
echo "fail"
fi
... ...
#!/bin/bash
pwd=`pwd`
target=`basename $pwd`
# kill
pid=`ps -C ${target} -o pid=`
if [ -n "$pid" ]; then
echo "Stopping old version, PID: ${pid}"
if [ "$1" = "-f" ]; then
# force shutdown
echo "Force shutdown..."
kill -9 $(ps -C ${target} -o pid=)
else
kill -9 $(ps -C ${target} -o pid=)
fi
# wait for program to stop
pid=`ps -C ${target} -o pid=`
while [ -n "$pid" ]; do
sleep 1
done
fi
# upgrade
if [ -f "${target}-new" ]; then
echo "Upgrading..."
if [ -f "${target}-backup" ]; then
backupdt=`date +%Y%m%d-%H`
mv "${target}-backup" "${target}-backup-${backupdt}"
fi
mv ${target} ${target}-backup
mv ${target}-new ${target}
echo "Upgrade Complete"
fi
# run
echo "Starting..."
./run.sh ${target}
echo "Done"
... ...
#!/bin/bash
pwd=`pwd`
target=`basename $pwd`
# kill
pid=`ps -C ${target} -o pid=`
if [ -n "$pid" ]; then
echo "Stopping old version, PID: ${pid}"
if [ "$1" = "-f" ]; then
# force shutdown
echo "Force shutdown..."
kill -9 $(ps -C ${target} -o pid=)
else
kill -9 $(ps -C ${target} -o pid=)
fi
# wait for program to stop
pid=`ps -C ${target} -o pid=`
while [ -n "$pid" ]; do
sleep 1
done
fi
echo "Done"
... ...