软件开发流程
1.明确需求
2.讨论制作产品原型(https://modao.cc,https://www.axure.com)
3.美工根据产品原型制作UI
4.前后端根据产品原型确定网络接口并制定网络数据传输协议(较多都是json,需要确定的是字段),写接口文档
5.前后端根据业务需要指定对应的数据对象,设计数据库
6.前后端各自编码,编码过程要指定规范文件目录,每个人的文件须放到对应的目录下,同时用git进行多人合作版本控制,个人进行编码时也要注意对自己代码进行测试并整合后才能上传到git,提出pull request请求,然后测试人员进行测试,并且其他人进行了代码审查之后方能合并到git
7.前后端分别进行单元测试和集成测试,最好是边编码边测试,每次改了代码都重新跑测试
8.前后端接口联调,后端进行并发测试
注意点:
判错从最开始就做到位;
只要返回err,检查!参数,检查!错误,一定返回并且写日志!
变量不能随便缩写,遵循行业规范;
变量命名,见名知意;
同一个包里面不要放太多文件(代码量不要太大),否则编辑器会很卡(代码补全搜索起来太慢),当大到一定程度时要考虑包重构,分包
善用搜索替换,包括但文件内搜索和整个项目文件的搜索,比如某些地方是模板式的,要改的时候就可以利用全局搜索替换,文件数比较多的话一个个改会非常耗费时间
Go:
defer 在return后处理错误 记得判了err之后再defer close,因为err后会返回nil
channel 实现消息分发
go routine
SQL语句要prepare,不然会被注入攻击
SQL如果要用事务要使用长事务,否则尽量使用SQL存储过程或函数,因为事务较慢
接口问题:
数据较多时要进行分页,一次返回数据尽量不要超过50条;
数据太大就写文件,然后发文件;
ubuntu@dongyang-K46CB:~/Emb/Emb_Server$ tree Project/src/ Project/src/ ├── emb ├── emb.config ├── emb.go ├── emb.sh ├── kill.sh ├── log ├── logs │ ├── logs.go │ └── 注意事项.txt ├── Network │ ├── dy_addGroupMember.go │ ├── dy_addGroupMemberList.go │ ├── dy_alterIcon.go │ ├── dy_createGroup.go │ ├── dy_deleteGroupMember.go │ ├── dy_getFile.go │ ├── dy_init.go │ ├── dy_judge.go │ ├── dy_router.go │ ├── dy_test_dbPage.go │ ├── dy_test_sendSystemMessage.go │ ├── dy_test_setData.go │ ├── errorCode.go │ ├── fs_chatMessageList.go │ ├── fs_helper.go │ ├── fs_judger.go │ ├── fs_sendTextMessage.go │ ├── fs_sessionList.go │ ├── fs_sessionListWithFriend.go │ ├── fs_sessionListWithGroup.go │ ├── fs_uploadFile.go │ ├── fs_wsLogin.go │ ├── fs_wsProcessor.go │ ├── httpConfig.go │ ├── init.go │ ├── pis_alterObjectData.go │ ├── pis_alterPassowrd.go │ ├── pis_checkOut.go │ ├── pis_deleteGroup.go │ ├── pis_getObjectData.go │ ├── pis_groupManagerList.go │ ├── pis_searchFriend.go │ ├── wsClients.go │ ├── wsRouter.go │ ├── zd_config.go │ ├── zd_getFriendList.go │ ├── zd_getGroupList.go │ ├── zd_getGroupMembers.go │ ├── zd_initargs.go │ ├── zd_register.go │ ├── zd_searchGroup.go │ └── zd_setGroupManager.go ├── public │ ├── audio │ │ └── 存聊天语音.txt │ ├── favicon.ico │ ├── file │ │ └── 存普通的聊天文件.txt │ ├── icon │ │ ├── 100000002.ico │ │ ├── default.ico │ │ └── 存头像.txt │ └── image │ └── 存聊天图片.txt ├── run.sh ├── SQL │ ├── db │ │ └── zd_db.go │ ├── FSDB │ │ └── FSDB.go │ ├── myDB │ │ └── db.go │ ├── util │ │ └── dbutil.go │ └── 注意事项.txt ├── token │ └── token.go └── 注意事项.txt
统一使用logs包进行调试输出,这样可以对输出内容进行统一控制,并通过debug包输出栈
1 package logs 2 3 import ( 4 "fmt" 5 "runtime/debug" 6 "strings" 7 ) 8 9 var debugMode = true 10 11 // Print 打印调用此函数的外层函数的文件和行号信息 12 // 13 // -- parent's parent func 14 // | 15 // -- parent func //打印这个函数的信息 16 // | 17 // -- PrintParent 18 // 19 func SetMode(mode bool) { 20 debugMode = mode 21 } 22 func Print(args ...interface{}) { 23 if !debugMode { 24 fmt.Println(args...) 25 return 26 } 27 28 stack := string(debug.Stack()) 29 stackLines := strings.Split(stack, "\n") 30 debugLine := strings.SplitAfter(stackLines[6], "/") 31 debugInfo := debugLine[len(debugLine)-1] 32 debugInfo = debugInfo[:len(debugInfo)-6] 33 a := []interface{}{debugInfo + ":"} 34 a = append(a, args...) 35 fmt.Println(a...) 36 } 37 38 // PrintParent 打印调用此函数的外层函数的外层函数的文件和行号信息 39 // 40 // -- parent's parent func //打印这个函数的信息 41 // | 42 // -- parent func 43 // | 44 // -- PrintParent 45 // 46 // 注意:main调用此函数,程序会崩溃! 47 func PrintParent(args ...interface{}) { 48 if !debugMode { 49 fmt.Println(args...) 50 return 51 } 52 stack := string(debug.Stack()) 53 stackLines := strings.Split(stack, "\n") 54 debugLine := strings.SplitAfter(stackLines[8], "/") 55 debugInfo := debugLine[len(debugLine)-1] 56 debugInfo = debugInfo[:len(debugInfo)-6] 57 a := []interface{}{debugInfo + ":"} 58 a = append(a, args...) 59 fmt.Println(a...) 60 }
经常修改的参数放到.config文件读入,不用每次都改代码 ,这样编译出来的可执行程序也可以随时改配置
SQL文件夹放置个人封的sql包,Network文件夹放网络接口代码,public文件夹放返回给前端的文件