点开工具、字典、anything


10.23 go

<h2>go web</h2> <h3>0. gitlab 地址</h3> <p><a href="http://119.23.216.19:10080/apiservice/go-darkroomliteweb">http://119.23.216.19:10080/apiservice/go-darkroomliteweb</a></p> <h3>1. 最外层的异常处理 (告警)</h3> <p>使用 app/middleware/recover.go </p> <h3>2. 路由注册</h3> <p>在 app/route.go 中定义即可</p> <pre><code>func InitRouter(Listen string) error { router := gin.Default() //add middleware to deal panic router.Use(middleware.Recover()) demo := router.Group("/demo") { demo.POST("/example1", controller.ExampleOne) // 在这里定义!!!! } return router.Run(Listen) }</code></pre> <h3>3. request 参数接收</h3> <p><img src="https://www.showdoc.cc/server/api/common/visitfile/sign/9d5466affcb7f6f5a916bb475d70b8b2?showdoc=.jpg" alt="" /></p> <h3>4. 参数验证</h3> <p>参数较少,暂时可以用结构体自己封装办法,也可以引入 &quot;gopkg.in/go-playground/validator.v9&quot; 来验证,待定</p> <pre><code> type exampleOneparams struct { Row int `form:"row" json:"row"` PageDepend int `form:"page_depend" json:"page_depend"` TagId int `form:"tag_id" json:"tag_id"` } func (ex *exampleOneparams)validate() error{ if ex.Row &lt; 1 || ex.Row &gt; 10{ return errors.New("row error") } if ex.PageDepend &lt; -1{ return errors.New("page_depend error") } if ex.TagId &lt; 1 { return errors.New("tag_id error") } return nil } </code></pre> <h3>5. 调用 service 层</h3> <p>引包然后使用办法即可</p> <pre><code>// 控制器调用 service 层, 获取小程序 + tab 下的 id idList, err := service.ListAppTabArticleId(appid, params.TagId, params.PageDepend, params.Row) if err != nil { commonGin.Fail(1, err.Error()) return } // service 层 func ListAppTabArticleId(appId string, tagId int, startId int, row int) ([]interface{}, error) { redisKey := rediskey.ListKey + appId + ":" + string(tagId) conn := common.Db.Redis.Get() defer conn.Close() reply, err := redis.Values(conn.Do("zRevRangeByScore", redisKey, startId, "-inf", "LIMIT", 0, row)) if err != nil { return nil, err } return reply,nil } </code></pre> <h3>6. 响应接口</h3> <p>由于 gin 框架的响应依赖于 *gin.Context</p> <p>所以封装了一个结构体做这件事,但是需要把 *gin.Context 作为参数传入</p> <p>详见 app/common/ginctx.go</p> <pre><code>commonGin := common.Gin{Ctx:c} // 注入 *gin.Context commonGin.Fail(common.WrongFormat,"格式错误") // 响应错误 commonGin.Success(exampleOneRespData{[]string{}, -1}) // 响应 success</code></pre> <h3>7. 中间件设置</h3> <p>在 app\middleware 下新建</p> <p>然后在 app/route.go 中使用即可</p> <pre><code> app\middleware func Recover() gin.HandlerFunc{ return func(c *gin.Context) { // 定义处理过程 c.Next() } } app/route.g router := gin.Default() //add middleware to deal panic router.Use(middleware.Recover()) // 使用办法 1,全局生效 demo := router.Group("/demo",middleware.Recover()) // 使用办法 2,特定路由生效 { demo.POST("/example1", controller.ExampleOne) } return router.Run(Listen) </code></pre> <h3>8. 配置读取</h3> <p>固定的配置比如 redis 的配置放在 app/config/config.json</p> <p>要经常动态变化的配置建议使用缓存作为配置</p> <h3>9. 初始化(注入)某些服务</h3> <p>在app/cmd/command.go 的 startService 中初始化</p> <h3>10. 日志打印</h3> <p>直接调用 common.Log (打印在根目录下的 log 文件) 这个日志组件暂时只是把 debug 和 info 记在一个文件,把 warn 和 error 记在一个。暂时只用于系统默认记录 todo 可以再封装一个用于记录业务的,分文件夹的 log 助手</p> <pre><code>common.Log.Error() </code></pre> <h3>11. 设置跨域</h3> <p>todo 使用中间件</p> <pre><code>func Cors() gin.HandlerFunc { return func(c *gin.Context) { origin := c.Request.Header.Get("Origin") if origin != "" { c.Header("Access-Control-Allow-Origin", origin) c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization") c.Header("Access-Control-Allow-Credentials", "true") } c.Next() } }</code></pre> <h3>12. 单元测试(办法测试)</h3> <p>todo 待研究</p> <h3>13. redis key</h3> <p>放在 app/rediskey</p> <pre><code>const ListKey = "z:set:template:article:list:" const ArticleDetails = "h:template:article:details" more 。。。。 </code></pre> <h3>14. 响应状态码</h3> <p>放在 app/common/errorcode.go</p> <pre><code>// 通用的业务错误码 const ( WrongParam = 40001 WrongFormat = 40002 AccessDenied = 40003 SessionExpired = 40004 WrongsProtoCode = 40005 UnknownError = 40006 ThirdApiError = 40007 InvalidRequest = 40008 NotFound = 40009 Exist = 40010 ) more 。。。。 </code></pre> <h3>15. 结构体定义</h3> <ul> <li> <p>request 参数结构体</p> </li> <li> <p>response 结构体</p> </li> <li>存储 redis 返回结果的结构体</li> </ul> <p>暂定放在 app/structs</p> <p>可能还有其他实践,再定。</p> <h3>16. 依赖引入办法</h3> <p>有两种方式,暂定用 go mod 的方式,详见项目下的 go.mod <img src="https://www.showdoc.cc/server/api/common/visitfile/sign/7fa84146b43d77e4b75dbc2ee44dbe5c?showdoc=.jpg" alt="" /></p> <h3>17. redis 池的配置问题 (重点)</h3> <p>理解下面几个的作用 <a href="https://www.jianshu.com/p/d36ab0c1e465">https://www.jianshu.com/p/d36ab0c1e465</a></p> <p><img src="https://www.showdoc.cc/server/api/common/visitfile/sign/02a933f0f7302988f73e2ae83f6ccfcb?showdoc=.jpg" alt="" /></p> <p><a href="https://www.showdoc.cc/344608763388140?page_id=3223718891102663">https://www.showdoc.cc/344608763388140?page_id=3223718891102663</a></p> <h3>18. 前台走完流程需要的接口:</h3> <ul> <li>首页 (/api/template/home_page_list) // ok,差地理位置</li> <li>详情页 (/api/template/details_list_new) // ok</li> <li>分享弹窗 (api/template/common_pool) // ok</li> <li> <p>轮播 (/api/template/v2/proto_broadcast_list) // ok</p> <hr /> </li> <li> <p>用户初始化 (/api/user/make_session) // ok</p> <hr /> </li> <li>流量分发 (/api/distribute/info)</li> <li> <p>流量分发上报 (/api/distribute/report)</p> <hr /> </li> <li>作者信息 (/api/author/get_info)</li> <li> <p>作者文章 (/api/author/get_article_list)</p> <hr /> </li> <li>获取赞赏列表 (/api/reward/getRewardList)</li> <li>调起支付接口 (/api/reward/toReward) 省略.....</li> </ul> <h3>其他 ing</h3> <p>程序的初始化过程</p> <p>mysql 的封装、</p> <p>文件名的定义规范等等。。。。</p>

页面列表

ITEM_HTML