V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
chaleaoch
V2EX  ›  Go 编程语言

gorm 结构体方式查询更新等操作忽略零值这个事儿影响不大吗?

  •  
  •   chaleaoch · 2021-08-25 20:41:20 +08:00 · 2926 次点击
    这是一个创建于 1188 天前的主题,其中的信息可能已经有所发展或是发生改变。
    譬如 bool 值 这种 false 是很常见的一种操作.

    在实际的开发中,如何处理这种情况. 都定义成指针? 还是 都用 map 更新?

    最佳实践是什么?

    谢谢大佬.
    第 1 条附言  ·  2021-08-26 12:15:18 +08:00
    然后我想问一下 针对 查询操作, 结构体 零值忽略问题 如何处理?
    我本地试了一下, select 针对零值 update 有效, 查询无效啊.


    谢谢谢谢.
    han3sui
        1
    han3sui  
       2021-08-25 20:50:36 +08:00 via iPhone   ❤️ 1
    应该用指针吧
    RTSmile
        2
    RTSmile  
       2021-08-25 21:10:49 +08:00
    注意 当通过 struct 更新时,GORM 只会更新非零字段。 如果您想确保指定字段被更新,你应该使用 Select 更新选定字段,或使用 map 来完成更新操作

    官网不是给了吗
    yrj
        3
    yrj  
       2021-08-25 21:11:11 +08:00 via iPad   ❤️ 1
    可以用 select 指定吧
    pluvet
        4
    pluvet  
       2021-08-25 21:25:16 +08:00   ❤️ 1
    这个确实很难受。目前是禁止用 Updates,都用 Save 、Select 等。
    chaleaoch
        5
    chaleaoch  
    OP
       2021-08-25 21:26:26 +08:00
    @RTSmile 明白. 谢谢.
    CEBBCAT
        6
    CEBBCAT  
       2021-08-25 23:17:24 +08:00
    没太明白,是数据库没有设计默认 DEFAULT '0'吗?还是写 DAO 的时候没有 UpdateColumn(map)?

    我遇到的场景都还是比较适合使用 map 指定更新字段的,不知道楼主的场景是怎样的。不过建议设置良好的 logger,这样可以对 gorm 的行为心里有底
    freakxx
        7
    freakxx  
       2021-08-25 23:19:19 +08:00   ❤️ 1
    开始写 go 这边的 crud 确实有这个难受的问题;

    后面把结构换为指针,
    塞进去的时候,判断值是否为 nil,
    nil 的话就略过。
    chaleaoch
        8
    chaleaoch  
    OP
       2021-08-25 23:37:47 +08:00
    @CEBBCAT
    没太明白,是数据库没有设计默认 DEFAULT '0'吗?
    -- 就是 update 一个 bool 从 True --> false 但是因为 false 是零值所以 update 失败.

    我遇到的场景都还是比较适合使用 map 指定更新字段的,不知道楼主的场景是怎样的。
    -- 我是 go/gorm 新手还没开始敲 go 代码. 就是看文档的时候遇到了这个说明所以很奇怪 真正的实际开发过程中是如何处理这个问题的. 我在脑子里空想 无论是指针 还是 values scan 都听麻烦的.
    map 合适吗? 我不知道. 因为目前我看到的有限的 go 代码用结构体用的都挺多的.

    所以上来问问有经验的大佬们.
    chaleaoch
        9
    chaleaoch  
    OP
       2021-08-25 23:39:02 +08:00
    @freakxx 那岂不是一堆指针 我看到有限的开源代码里面的指针并不很多.
    ihipop
        10
    ihipop  
       2021-08-25 23:43:02 +08:00 via Android
    @pluvet save 不用 select 会整个 struct 全部写库,你读出的数据是有可能滞后的,导致库内数据被覆盖
    freakxx
        11
    freakxx  
       2021-08-25 23:48:47 +08:00
    @chaleaoch #9

    是滴,代码会有点脏,后续可能需要再重新统一下

    但如果不这么搞,确实没好办法,挺恶心的。。。
    你根本不知道你从外面塞进来的 0 是真的 0 还是默认的 0
    pluvet
        12
    pluvet  
       2021-08-25 23:52:51 +08:00
    @ihipop 倒是可以事务+行锁,不过就更麻烦了。你有没有好办法?
    ooh
        13
    ooh  
       2021-08-26 00:05:13 +08:00
    hpeng
        14
    hpeng  
       2021-08-26 00:21:28 +08:00 via iPhone
    go 的破问题,感觉除了指针没什么更好的解法了
    CEBBCAT
        15
    CEBBCAT  
       2021-08-26 00:26:16 +08:00   ❤️ 1
    @chaleaoch #8 哈哈,我更愿意称之为失败的 update,而不是 update 失败。零值问题手动使用 map 指定要更新的字段就好了,我想麻烦不是很多。如果你不想用 map 的方式,楼上说的 Select 也可以考虑一下。他们其实核心作用都是明明白白地告诉 ORM,你要更新的字段是哪些

    结构体当然很常用呀,但我想 gorm 这边只好依着它来了。其实我之前都是手写 SQL 的,没错,手动 Scan Field 。我觉得即使是手写 SQL 工作量也不会多出来多少吧,所以也许你可以试用一下 DB.Exec() ?哈哈,祝好运
    ihipop
        16
    ihipop  
       2021-08-26 07:26:00 +08:00 via Android   ❤️ 1
    @pluvet 我想表达的和事物锁没有关系,我的意思是说 save 会保存整个 struct 的所有值,如果你新建,所有 0 值字段都会写入,如果你更新,所有先前读出的映射到 struct 的字段包含 struct 自带的 0 值哪怕没有修改过,都会被回写,而这些年当前业务没修改的字段在数据库可能已经被其它业务改过,你光用 save 就会导致这些业务数据回退,所以必须 save 配合 select 指定你修改的业务字段,这么麻烦还不如用 updates+map 。
    labulaka521
        17
    labulaka521  
       2021-08-26 09:50:14 +08:00 via iPhone
    用 save 前端会返回这个结构体的时候数据,偶尔会用 update map 来更新
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2421 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:01 · PVG 00:01 · LAX 08:01 · JFK 11:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.