统一代码结构顺序
在同一文件中,如果存在类型(结构体)、常量、变量、方法(公共/私有)定义的时候,最好按照以下顺序组织代码结构,以方便维护:
- 类型定义(结构体定义)
- 常量定义
- 变量定义
- 方法定义(公共)
- 方法定义(私有)
例如:
// 类型定义 type Xxx struct {} // 常量定义 const ( internalConstName = "xxx" ) // 变量定义 var ( internalVariable = "xxx" ) // 方法定义(公开) func GetXxx() { } // 方法定义(私有) func doGetXxx() { }
不要问我为什么?在团队开发中一定要有统一的规范,方便大家更好的理解代码,降低理解成本。
配置文件的管理
goframe建议大家使用配置文件,以便区分不同的运行环境连接不同的DB、CACHE、NSQ、三方的AKSK等配置信息。
这些配置文件一定是要加到gitignore中的,避免导致运行环境的混乱。
当我们有修改配置文件时,一定要记得同步修改多个环境的配置文件,避免导致未知问题。
当排查业务逻辑拍查不到原因时,想想是不是忘记修改了配置文件,这虽然是个低级错误,但确实坑了不少人。
尤其当遇到了本地环境运行正常,但是测试环境或者生产环境运行异常,且代码完全一致。首先排查机器是否正常,机器运行状态没问题后马上排查一下是不是配置文件不一致。
调试技巧
我习惯在项目中搞一个test文件,进行功能测试。
绑定cmd
首先,在main.go中绑定gcmd,允许通过cmd运行test文件
package main import ( "github.com/gogf/gf/os/gcmd" "myApp/app/test" ) func main() { . . . _ = gcmd.BindHandle("test", test.Run) //调试脚本统一写在这里 避免混淆 _ = gcmd.AutoRun() }
test文件
package test func Run() { testDemo() } func testDemo() { //这是结构体 var req *notify.NotifyServer //这是json jsonInput := `{"msg_type":x,"source":x,"msg_send_time":x,"msg_data":{"xx":"xxxxxxx"}}` //把json转成结构体 err := gconv.Struct(jsonInput, &req) if err != nil { logs.Info("test", "转换错误:%v", err) } g.Dump("req:", req) _ = f.StatusComfirm(context.Background(), req) }
运行cmd
通过下述命令启动测试文件
go run main.go test
这样做的好处至少有2点:
- 不需要借助postman或者apipost就能调试自己的项目
- 当然我们也可以直接写到脚本文件中,但是那样做可能会和正常的脚本逻辑混淆。我们把需要进行测试的功能写到test中,能够避免歧义,降低团队的理解成本。
元数据 gmeta
作用:
主要用于嵌入到用户自定义的结构体中,比如声明对应的数据库
通过标签的形式给gmeta包的结构体打上自定义的标签内容,在运行时可通过Data/Get方法获取这些自定义的标签内容
package main import ( "fmt" "github.com/gogf/gf/util/gmeta" ) func main() { type User struct { gmeta.Meta `orm:"user" db:"mysql"` Id int Name string } //通过Data获得结构体中的gmeta元数据标签,返回map类型 fmt.Println(gmeta.Data(User{})) //map[db:mysql orm:user] //获得gmeta元数据标签的特定值 fmt.Println("orm:", gmeta.Get(User{}, "orm")) //orm: user }
打印结果
map[db:mysql orm:user] orm: user
在项目中如果有类似需求,那么gmeta是个非常不错的选择。