查询时避免返回对象初始化及sql.ErrNoRows判断

    一个反面例子:

    在该例子中,实际返回的out对象由于对象初始化的缘故有了默认值(无论SQL是否查询到数据),并且sql.ErrNoRows的判断增加了代码逻辑中对error处理的复杂度。

    建议改进如下:

    1. func (s *sTask) GetOne(ctx context.Context, id uint64) (out *entity.ResourceTask, err error) {
    2. err = dao.ResourceTask.Ctx(ctx).WherePri(id).Scan(&out)
    3. if err != nil {
    4. return
    5. }
    6. if out == nil {
    7. }
    8. return

    更多的介绍请参考:

    复杂类型尽量使用json存储,便于Scan到对象时自动化转换,避免自定义解析

    举一个🌰。假如我们需要实现产品售卖规格列表,其中包含可选择的分片数量、分片容量以及副本数量,如下图(非现网代码,仅供示例学习):

    其中的resources, shards, replicas我们定义为json格式,目的是可以存储自定义的资源、分片、副本规格列表(非顺序性)。那么我们的go struct定义如下:

    1. // SellSpec 是通过GoFrame工具自动生成的数据结构,由工具维护。
    2. type SellSpec struct {
    3. Id uint `description:"主键"`
    4. Product string `description:"产品名称"`
    5. Resources string `description:"资源规格(cpu:memory),例如:[\"0:0.25\", \"0:1\", \"1:2\"]"`
    6. DiskMin int `description:"磁盘最小容量"`
    7. DiskStep int `description:"磁盘递增大小"`
    8. Shards string `description:"分片规格,例如:[1,3,5,8,12,16,24,32,40,48,64,80,96,128]"`
    9. Replicas string `description:"副本规格,例如:[1,2,3,4,5,6,7,8,9,12]"`
    10. UpdatedAt *gtime.Time `description:"更新时间"`
    11. }
    12. // SellSpecItem 是扩展entity的自定义数据结构,其中部分字段被覆盖为了数组类型。
    13. type SellSpecItem struct {
    14. entity.SellSpec
    15. Resources []string `dc:"资源规格"`
    16. Shards []int `dc:"分片规格"`
    17. Replicas []int `dc:"副本规格"`
    18. }

    那么在程序中我们可以这么来写入和查询数据记录。

    数据写入: