Skip to content

GoFrame避坑指南和实践干货(2)

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情

用GoFrame已经开发了一段时间,今天为大家分享避坑指南和实践干货。这些坑并不是框架设计者的问题,更多的是我作为初学者的各种摸石头过河~

前段时间有整理一篇# GoFrame避坑指南和实践干货,这篇算是续集吧。

Redis Setex

首先我们要知道这个概念:Redis Setex 命令为指定的 key 设置值及其过期时间。如果 key 已经存在, SETEX 命令将会替换旧的值。

在goframe中是支持这么操作的:

go
_, err = g.Redis().Do("SETEX", redisKey, 86400, res)

rune的使用

首先我们要知道rune是int32的别名:

go
type rune = int32

golang中string底层是通过byte数组实现的。中文字符在unicode下占2个字节,在utf-8编码下占3个字节,而golang默认编码正好是utf-8。

len([]rune("王中阳"))的长度,一个中文返回一个长度,而不是返回3个字符长度。

gvalid数据校验

在goframe中,我们可以在结构体中设置校验规则,不需要在业务逻辑中进行判断,这样能使我们的代码更清晰。

示例

go
//校验地址 if err := gvalid.CheckStruct(ctx, data.Address, nil); err != nil {    response.ParamErr(r, err) }

其中:data.Address 是需要校验的数据。在执行校验地址之前已经把传入的数据赋值到了对应的结构体:

go
var data *define.OrderServiceCreateReq if err := r.Parse(&data); err != nil {    response.ParamErr(r, err) }

其中:define.OrderServiceCreateReq 的定义如下:

go

```type OrderServiceCreateReq struct {    SellerId       uint                    `json:"sellerId"`    AppId          int                     `json:"appId"`    ChannelId      int                     `json:"channel_id"`    OrderSn        string                  `p:"orderSn" v:"orderSn@required#orderSn 必须传递"`    Spu            []*OrderServiceSkuReq   `p:"spu" v:"spu@required#请输入spu"`    Address        *OrderServiceAddressReq `p:"address" v:"address@required#请输入address"`    StrictMode     bool                    `json:"strictMode"`    PayType        int                     `p:"payType" v:"payType@integer|in:0,1,2"` //0 余额 1 支付宝 2 微信    Rate           int                     `json:"rate"`    IsSplitMoney   int                     `json:"is_split_money"`    AccountBalance int                     `json:"account_balance"`    ErrId          int                     `json:"errId"`    AccountPhone   string                  `json:"account_phone"`    AppKey         string    SiteId         uint `json:"site_id"` }``

其中:Address 对应的是结构体类型:OrderServiceAddressReq

我们在看一下OrderServiceAddressReq是怎么定义的?校验规则就是在这里定义的:

``` go

```type OrderServiceAddressReq struct {    Consignee   string `v:"required|length:2,15#请输入consignee|收货人长度:min到:max位"`    Phone       string `v:"phone@required|phoneNew#请输入phone"`    Province    string `v:"required#address.province 必须传递"`    City        string `v:"required#address.city 必须传递"`    Area        string `v:"required#address.area 必须传递"`    Street      string    Description string `v:"required|max-length:50#请输入description|详细地址最大长度不超过:max个字"` }``

其中:#的后面写的就是校验提示

# redis锁 避免重复请求

思路非常简单:因为redis相较于关系型数据库,读写性能更高;

这种加锁的思路简单高效:

``` go
func (s *orderApi) Create(r *ghttp.Request) {    var data *define.OrderServiceCreateReq    if err := r.Parse(&data); err != nil {       response.ParamErr(r, err)    }    key := "order:"    key += r.GetString("appId")    key += ":"    key += gmd5.MustEncryptString(r.GetBodyString())    val, err := g.Redis().DoVar("GET", key)    if err != nil {       response.ApiResponse(r, tools.Code{}.BackErr())       return    }    if val.Int() > 0 {       response.ApiResponse(r, tools.Code{}.BackErrMsg("请勿重复请求"))       return    }    _, _ = g.Redis().DoVar("SETEX", key, 3, 1) }

查文档

对了,goframe的文档做的真心不错,对开发者非常友好。

说实话,作为有几年工作经验的程序员,换一门语言进行开发难度并不大。

实现业务逻辑的思路是相通的,差别就是实现语法上,或者是语言对某些场景的支持:比如go对高并发的支持、Java对锁的支持、PHP对数组集合的支持。

我的习惯是这样:在确定了业务逻辑之后,整理好实现思路,先写伪代码,避免陷入切换语言(从PHP到Go)的不适(总是会陷入想优化代码的细枝末节里);伪代码写完后,再开始撸业务逻辑,遇到不清楚的语法直接查文档,这样做,思路就会很清晰。

比如:我要做城市信息匹配,输入参数是“北京”或者“唐山市”(直辖市不带市),但是我的数据库中存储的是“北京市”,匹配不到。

一个解决思路就是:校验一下输入参数,如果不包括“市”,就在原有的输入参数后追加一个“市”。

image.png

image.png

一查文档果然封装好了方法,拿来就用喽:

go
city := address.City if !gstr.Contains(city, "市") {    city = city + "市" }

这也是我推荐goframe的理由之一,文档友好,功能强大~

最后

感谢阅读,欢迎大家三连:点赞、收藏、投币(关注)!!!

8e95dac1fd0b2b1ff51c08757667c47a.gif

🚀 学习遇到瓶颈?想进大厂?

看完这篇技术文章,如果还是觉得不够系统,或者想在实战中快速提升?
王中阳的就业陪跑训练营,提供定制化学习路线 + 企业级实战项目 + 简历优化 + 模拟面试。

了解训练营详情