The Go Programming Language
› http://golang.org/
› Go Playground
Go Projects
› Revel Web Framework
qW7bo2FbzbC0

被 go 语言的 json.Marshal 恶心到了

  •  
  •   qW7bo2FbzbC0 · Jul 17, 2024 · 19508 views
    This topic created in 841 days ago, the information mentioned may be changed or developed.

    我的需求是,输入 sql ,返回序列化后的 json 结果。

    在 python 中,官方库就可以返回[{'col1': 1, 'col2': '2', 'col3': true}....] 这种带类型的 json 结果。

    在 go 中如果已知 sql 返回的列数和列类型,也可以构造一个 struct 进行数据映射,然后用json.Marshal转为 json 。

    如果 sql 返回的列数和行类型未知,就很难受了,在 go/mysql 的官方 wiki 案例 中对于匿名的结果,使用了 interface 或者 sql.RawBytes ,但这两种替代方式在json.Marshal后都变成了 base64 encode 后的 string ,既丢失了类型也变异了结果( https://stackoverflow.com/questions/32501784/the-sqlx-library-gives-weird-base64-encoded-looking-results)

    请问各位在实际业务中遇到这个问题是怎么处理的?

    在其他语言中很自然的 object 序列化为原类型,在 go 的 json.Marshal 中怎么就全变成 string 了

    Supplement 2  ·  Jul 24, 2024
    131 replies  •  2024-10-22 17:49:42 +08:00
    1  2  
    ❮ ❯
    yrzs
    yrzs
    Jul 17, 2024
    1
    FrankFang128
    FrankFang128
    Jul 17, 2024
    2
    没遇到过,没看懂
    3img
    3img
    Jul 17, 2024
    3
    如果是不知道指针的类型,可以用反射啊
    dzdh
    dzdh
    Jul 17, 2024❤️1
    4
    我翻译一下。

    up 想要 go 实现 php 的 json_encode(PDO->fethcAll()) 不定义 struct
    NessajCN
    NessajCN
    Jul 17, 2024
    5
    首先 Marshal 是序列化,Unmarshal 是反序列化, 也就是从 byte 到 go struct 应该用 Unmarshal
    其次,对于未知的返回类型一般不 Unmarshal , 直接从 interface 里取键值,go 自带返回 ok 判断是否有这个 key
    譬如
    ```go
    type SqlResult map[string]interface{}
    var res SqlResult
    if col1,ok := res["col1"].(int32); ok {
    //...
    }
    ```
    povsister
    povsister
    Jul 17, 2024
    6
    你适合用 python
    sagaxu
    sagaxu
    Jul 17, 2024
    7
    根据 ColumnType 判断一下字段类型,自己写个转换,把[]byte 和[]uint8 都转成 string
    laikicka
    laikicka
    Jul 17, 2024
    8
    你适合用 PHP
    zxdstyle
    zxdstyle
    Jul 17, 2024
    9
    这不是 go 和 python 的区别,是强类型语言与弱类型语言的区别
    Sezxy
    Sezxy
    Jul 17, 2024
    10
    @zxdstyle 其实 python 也是强类型语言
    sagaxu
    sagaxu
    Jul 17, 2024
    11
    @laikick 除了 PHP ,Python 和 Java 也行,这件事情上,唯独 Go 比较大道至简
    james122333
    james122333
    Jul 17, 2024 via Android
    12
    你可以用 map[string]any 或 json.RawMessage
    james122333
    james122333
    Jul 17, 2024 via Android
    13
    map[string]any, []any...族繁不及备载
    Nazz
    Nazz
    Jul 17, 2024
    14
    要修改下结构体定义, 例如把 []uint8 换成 []uint16
    james122333
    james122333
    Jul 17, 2024 via Android
    15
    看 col 举例应该是[]map[string]any
    ChrisFreeMan
    ChrisFreeMan
    Jul 17, 2024
    16
    OP 赶紧跑吧你完了
    luhengyuorang
    luhengyuorang
    Jul 17, 2024
    17
    最开始用 py 或者 php 的来写 go ,很容易有代入感,经常看到别人把 go 写成 php
    dcalsky
    dcalsky
    Jul 17, 2024❤️11
    18
    收收 python 、js 、php 味。go 的正规业务里,都要得先定义 struct ,不到万不得已不用 map[string]any
    liaohongxing
    liaohongxing
    Jul 17, 2024
    19
    总结不适应强类型
    rekulas
    rekulas
    Jul 17, 2024
    20
    go 真冤 完全没看懂这跟 go 有什么关系
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    21
    @sagaxu 我去查了下 grafana 的代码,又查了下 sof ,对于未知返回类型的查询,的确是对各个类型自己去重新实现映射/序列化

    和 @NessajCN 说的差不多

    但是 java, c#这种都可以 getObject,然后直接对 Object 序列化出带类型的 json
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    22
    @sagaxu @NessajCN @james122333 但是 go 语言中,用 interface 或者 any 来模拟 java c#这种 getObject ,然后序列化,结果就是 base64 encode 后的 string
    cuiweiqiang
    cuiweiqiang
    Jul 17, 2024
    23
    既然用 sql 了,为啥还会存在“行类型未知”这种场景?
    james122333
    james122333
    Jul 17, 2024 via Android
    24
    是最好定义 struct 外加上泛型
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    25
    @dcalsky 肯定是有传入黑箱 sql ,返回 json 结果的场景,没遇到不等于没有。这和 python 、js 、php 味没关系,java c#都正常
    wildlife
    wildlife
    Jul 17, 2024
    26
    标准的 JSON 不是只能使用 "" 双引号包围的任意数量 Unicode 字符的集合吗?
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    27
    @cuiweiqiang 用 java 模拟 mysql 命令行工具,这个场景是不是 sql 已知,行类型未知?
    james122333
    james122333
    Jul 17, 2024 via Android
    28
    @qW7bo2FbzbC0

    你不能直接就一个 any 最起码知道它是字典阵列 不知道就先 json.RawMessage 根据内容 parse 一下用字典或阵列装
    nxcdJaNnmyF9O90X
    nxcdJaNnmyF9O90X
    Jul 17, 2024
    29
    你适合用 PHP 典型的脚本语言思想
    james122333
    james122333
    Jul 17, 2024 via Android
    30
    阿... Marshal 的话就直接 Marshal 成 json.RawMessage 就好了
    把字段定义成 json.RawMessage 即可
    MoYi123
    MoYi123
    Jul 17, 2024❤️1
    31
    @qW7bo2FbzbC0 怎么可能是 base64 后的 string 啊, 贴个例子看看. 八成是 unicode 吧, 提醒一下, json 必须是 utf8 编码的.
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    32
    在 go/sql 中,interface 或者 any 会返回[]byte ,在 json.Marshal 中,[]byte 会被序列化成 base64 encode 字符串


    `Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the null JSON value.`

    @NessajCN @sagaxu
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    33
    https://forum.golangbridge.org/t/json-encode-byte-array-as-hex-string-instead-of-base64/26751

    ```
    One must use reflection to walk and copy the original object replacing byte arrays with the user-defined type for which the MarshalJSON method is defined, but there’s probably no better way. An even uglier alternative is to post-process the JSON.
    ```
    fregie
    fregie
    Jul 17, 2024
    34
    犯懒就用 js python 就好了,何必选个强类型语言给自己找罪受呢
    Felldeadbird
    Felldeadbird
    Jul 17, 2024
    36
    用一门新语言时,最怕就是拿别的语言对比新学的语言。

    不想麻烦就定义结构体,一次定义全代码收益,要像脚本语言那么自然,就得多写一些代码转换。
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    37
    @fregie 1 、项目定型是这个语言。2 、类似的蹩脚问题不止这一个,在 go1.8 之前代码里面好多 inteface 飞来飞去,不仅丢失了类型还影响类型安全。 我讨厌 interface 转来转去也是犯懒,我觉得 go/sql 和 json.Marshal 对于匿名类型查询不友好也是犯懒?你扣帽子是什么态度?
    cs8425
    cs8425
    Jul 17, 2024
    38
    @qW7bo2FbzbC0 因为 json 的 string 必须为 UTF-8 而[]byte 不一定是 UTF-8
    Jinnrry
    Jinnrry
    Jul 17, 2024 via Android
    39
    你可以试试 map any any

    不过建议你写 php
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    40
    同样是使用匿名类型去序列化,c#正确识别出了 Number 类型

    ```c#
    // See https://aka.ms/new-console-template for more information
    using System.Text.Json;
    using MySqlConnector;


    using var connection = new MySqlConnection("Server=127.0.0.1;User ID=root;Password=****;Database=test");
    connection.Open();

    using var command = new MySqlCommand("select id from t1;", connection);
    using var reader = command.ExecuteReader();
    var x = new Dictionary<string, object> { };
    while (reader.Read())
    {
    x["name"] = "name";
    x["value"] = reader.GetValue(0);
    }
    Console.WriteLine(JsonSerializer.Serialize(x));
    ```

    输出结果为

    ```js
    {"name":"name","value":1}
    ```
    jsonparse
    jsonparse
    Jul 17, 2024
    41
    建议用 python
    HanSonJ
    HanSonJ
    Jul 17, 2024
    42
    可以用 gjson
    NessajCN
    NessajCN
    Jul 17, 2024
    43
    @qW7bo2FbzbC0 不然列,[]byte 本来就已经是 byte array 了,你再把他序列化一遍想变成啥?
    vczyh
    vczyh
    Jul 17, 2024
    44
    sql.RawBytes 就是[]byte, []byte 序列化 json 的时候就是应该使用 base64 ,不然控制字符怎么打印?你不能认为都是[]byte{97, 98} ab 这种可打印字符。

    不符合你的预期而已,你都用[]byte 接收据了,类型肯定丢失了。
    elevioux
    elevioux
    Jul 17, 2024
    45
    life is short , use php
    james122333
    james122333
    Jul 17, 2024
    46
    @qW7bo2FbzbC0

    package main

    import(
    "encoding/json"
    )

    func main() {
    m := map[string]any {
    "name": "name",
    "value": 1,
    }
    b, _ := json.Marshal(m)
    println(string(b))
    }

    {"name":"name","value":1}
    kkk9
    kkk9
    Jul 17, 2024❤️2
    47
    惯性思维、学艺不精
    wysnxzm
    wysnxzm
    Jul 17, 2024
    48
    总结:go 没问题,是你不会自适应
    james122333
    james122333
    Jul 17, 2024
    49
    package main

    import(
    "encoding/json"
    )

    func main() {
    m := map[string]any {
    "name": "name",
    "value": json.RawMessage([]byte("1")),
    }
    b, _ := json.Marshal(m)
    println(string(b))
    }

    {"name":"name","value":1}
    lysShub
    lysShub
    Jul 17, 2024
    50
    看你的需求,直接存 string 字符串,查询的时候用 gjson 读。当然这样性能和安全就下降了一个层次
    james122333
    james122333
    Jul 17, 2024
    51
    @qW7bo2FbzbC0

    我已经回了 n 次 json.RawMessage...
    lesismal
    lesismal
    Jul 17, 2024
    52
    定义跟 sql table 对应的 struct 是必要的, 自动绑定后用 json 去操作 struct 就没这个问题了.
    个人觉得 orm 不好用, 自己搞了份 raw sql+自动绑定的库, 有兴趣可以试试, 例子:
    https://github.com/lesismal/sqlw_examples/blob/main/mysql/db/db.go#L101
    james122333
    james122333
    Jul 17, 2024 via Android
    53
    @lesismal

    你写的这个楼主说的 sqlx 已经有了
    然后我在公司又把它封装成无 join 功能的 orm
    xFrye
    xFrye
    Jul 17, 2024❤️4
    54
    我觉得用一门语言的原则是用他的推荐方式去实现代码,而不是想着怎么这垃圾语言没法像谁谁那样写。。。
    skuuhui
    skuuhui
    Jul 17, 2024
    55
    interface{}
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    56
    同样是使用匿名类型去序列化,java 也正确识别出了 Number 类型
    ```java
    package com.test.Demo;

    import java.sql.*;
    import java.io.*;
    import java.util.*;
    import com.google.gson.*;

    public class Demo {
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
    static final String USER = "root";
    static final String PASS = "******";

    public static void main(String[] args) {
    Connection conn = null;
    Statement stmt = null;
    try{
    Class.forName(JDBC_DRIVER);
    conn = DriverManager.getConnection(DB_URL,USER,PASS);
    stmt = conn.createStatement();
    String sql = "select id from t1";
    ResultSet rs = stmt.executeQuery(sql);
    HashMap<String, Object> x;
    x = new HashMap<String, Object>();

    while(rs.next()){
    Object id = rs.getObject("id");
    x.put("name", "name");
    x.put("value", id);
    }
    Gson gson = new Gson();
    System.out.println(gson.toJson(x));
    } catch (Exception e){
    e.printStackTrace();
    }

    }

    }

    ```
    pkoukk
    pkoukk
    Jul 17, 2024
    57
    map[string]any
    然后根据你说的,某个标识字段,判断类型,再用 https://github.com/mitchellh/mapstructure
    转成你要的实际 struct
    ScepterZ
    ScepterZ
    Jul 17, 2024
    58
    这是 sql 库返回的对象不好序列化的问题,不是 json 库的问题,要解决的话也应该是 sql 库这边来处理,给一个方便打印的办法
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    59
    @james122333 json.RawMessage 是可行的,但是看起来和 java/c#的模式不同,从 go/sql 映射出来的 interface 变成了[]byte 而不是(interface).type ,而且官方文档好像也推荐用 interface 或者 sql.RawBytes 来接未知类型
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    60
    @ScepterZ 是的,我说错了,是 go/sql 返回的 interface 无法直接序列化
    veni2023
    veni2023
    Jul 17, 2024
    61
    @pkoukk 遇到过这个包在弱类型解析时有精度丢失的情况
    houzhiqiang
    houzhiqiang
    Jul 17, 2024
    62
    我猜想要的效果是这样的:
    ```python
    import pymysql
    import pymysql.cursors


    connect = pymysql.connect(
    host="example.com", port=3306, user="user", password="password", database="database_name",
    cursorclass=pymysql.cursors.DictCursor,
    )
    with connect.cursor() as cursor:
    cursor.execute(
    """select * from users limit %(param_limit)s""",
    args={"param_limit": 2}
    )
    results = cursor.fetchall()
    print(results)
    # [
    # {'id': 13, 'birthday': datetime.date(1900, 1, 1), 'create_time': datetime.datetime(2020, 9, 3, 16, 56, 39)},
    # {'id': 39, 'birthday': datetime.date(1900, 1, 1), 'create_time': datetime.datetime(2020, 9, 14, 17, 5, 1)}
    # ]
    ```
    vczyh
    vczyh
    Jul 17, 2024
    63
    @qW7bo2FbzbC0

    func TestMy(t *testing.T) {
    db, err := sql.Open("mysql", "root:123@/test")
    if err != nil {
    t.Fatal(err)
    }
    defer db.Close()

    rows, err := db.Query("SELECT id FROM t1")
    if err != nil {
    t.Fatal(err)
    }

    for rows.Next() {
    var id any
    if err := rows.Scan(&id); err != nil {
    t.Fatal(err)
    }
    m := map[string]any{
    "value": id,
    }
    b, err := json.Marshal(m)
    if err != nil {
    t.Fatal(err)
    }
    t.Log(string(b))
    }
    if err := rows.Err(); err != nil {
    t.Fatal(err)
    }
    }

    {"value":1}


    用 any 接收数据,返回的类型由驱动实现决定,database/sql 只提供接口,驱动负责返回 sqldriver.Value ,所以真不是 Go 语言的问题。
    jlkm2010
    jlkm2010
    Jul 17, 2024
    64
    go 的语法很怪异
    kkbblzq
    kkbblzq
    Jul 17, 2024
    65
    这跟 json 都没有关系,而是 sql 类型和 go 类型之间的转换问题。
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    66
    @vczyh 你这个是什么驱动?
    lesismal
    lesismal
    Jul 17, 2024
    69
    @james122333
    1. orm 是非常不好的选择, 中小项目倒是还可以, 大项目大数据量的, 用 orm 存在一些不确定性可能导致性能风险, 所以我都是禁止团队试用 golang orm 的
    2. 还有生成代码的 sqlc 这种, 性能当然是最友好但用起来也有点麻烦, 因为一些业务是上下文比较复杂的, 单纯生成一段 sql 对应的 go 代码还需要 ctrl cv 而且还要修改对应的地方, 功能修改的时候比较麻烦
    3. sqlx 简化了一些 binding, 但也把一些简单的复杂化了, 比如又有 Select 又有 Get, 比如 Insert 缺少 struct 的自动绑定(我没深入使用只是看它文档和例子), 综合下来我觉得它少了一些可以真正节约体力的但多了不少没必要的, 所以对我来说病不好用

    所以以前还是继续标准库 raw sql, 直到我实在忍不了标准库 raw sql 自己搞了这个
    lifei6671
    lifei6671
    Jul 17, 2024
    70
    @qW7bo2FbzbC0 #37 没看到别人扣帽子,反而是你自己情绪化,人家都说了你用不惯 go 就换成你喜欢的语言好了,再说了,interface 满天飞就是犯懒的行为。
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    71
    @lifei6671 1.8 之前还有什么办法避免 Interface 满天飞?
    lesismal
    lesismal
    Jul 17, 2024
    72
    @james122333 我这个就是简简单单几点:
    1. 鼓励明确定义 table 对应的 struct, 用明确定义的 struct 操作 sql, 这个 struct 自己手写也好用工具生成也好, 都挺方便的
    2. 鼓励 raw sql, 避免 orm 之类的可能生成了性能不友好的语句造成性能事故
    3. 框架尽量自动映射/绑定 sql table 和 struct, insert/update/select 这些与 struct 映射绑定操作密切的都很轻松用 struct 操作
    4. 奥卡姆剃刀原则, 不提供 orm, 不提供那么多没什么必要的垃圾接口
    fregie
    fregie
    Jul 17, 2024
    73
    @qW7bo2FbzbC0 "我觉得 go/sql 和 json.Marshal 对于匿名类型查询不友好也是犯懒?"
    不友好的意思是指不能用方便又稳定的办法解决这个问题,只能用麻烦但是稳定的方式解决.
    你认为这不友好难道不是犯懒吗?
    BTW,何必这么敏感,犯懒又不是什么攻击性的词语,我自己也经常犯懒,人皆是如此,只是要可能会付出代价
    这个世界还是挺美好的,没必要一进入互联网就进入攻击模式
    superrichman
    superrichman
    Jul 17, 2024
    74
    @zxdstyle 你想表达的是动态语言和静态语言的区别
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    75
    @fregie 犯懒字面上是贬义词吧,你觉得不是攻击性的,那你可以自己多读几遍,不要替别人做决定。稳定不稳定不知道,写起来麻烦的代码后面维护起来肯定更麻烦
    lesismal
    lesismal
    Jul 17, 2024
    76
    @qW7bo2FbzbC0 #71
    interface 满天飞是当时写这些垃圾代码的人的问题, 不是 golang 自己的问题.
    正确姿势本来就应该避免 interface 满天飞, 我看到很多喜欢搞 interface 满天飞的, 是 php nodejs 之类的转 go 的人居多, 这也不能全怪他们, 毕竟以前语言习惯已经信手拈来了, 刚开始未必能意识到这样会带来工程上的问题, 更何况有时候赶工只追求先搞定业务
    c/cpp 或者一些新手上路就是 go 的, 姿势正常的人多些

    接手别人的屎山不是 OP 的错, interface 满天飞不是 golang 的错, OP 要怪就都怪写屎山的人吧
    leonshaw
    leonshaw
    Jul 17, 2024
    77
    用 ScanType 反射?
    iyaozhen
    iyaozhen
    Jul 17, 2024
    78
    用 go 千万不要和别的语音比 不要之前语言思维定势。不然坑还更多
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    79
    按楼上说的 json.RawMessage 解决了,我没有想到要去 json 命名空间里找类型
    @leonshaw
    james122333
    james122333
    Jul 17, 2024
    80
    @qW7bo2FbzbC0

    这你要问 driver 为什么输出的格式是[]byte 也就是你上面贴的那个 lib
    目前没时间研究 你自立自强点
    至於 json 对[]byte 处理是合理的
    james122333
    james122333
    Jul 17, 2024❤️1
    81
    @lesismal

    我目前弄的只有简单的 crud 和建立表 join 没整其他指令也没整 还是基於 sqlx 整的 只是用原生的 sql 应该也都差不多
    根据 struct 中 tag 讯息拼接字符串 反射方法都已经写好 验证下来没问题 会这样搞主要是想偷懒点
    fregie
    fregie
    Jul 17, 2024
    82
    @qW7bo2FbzbC0 嫌麻烦而想放弃,这不是犯懒?
    gowk
    gowk
    Jul 17, 2024
    83
    回帖不支持代码,,看着就非常难受!
    zzhaolei
    zzhaolei
    Jul 17, 2024
    84
    show me the code
    lloovve
    lloovve
    Jul 17, 2024 via iPhone
    85
    这边建议转 rust 试试
    woodfizky
    woodfizky
    Jul 17, 2024
    86
    Python 是强类型语言,不管用 ORM 还是原生 SQL 一样要处理类型问题。

    不懂某些评论为什么要说有 Python 味,吐槽之前好好调查一下再给出观点很难是吗?
    zzhaolei
    zzhaolei
    Jul 17, 2024
    87
    @lesismal
    “1. orm 是非常不好的选择, 中小项目倒是还可以, 大项目大数据量的, 用 orm 存在一些不确定性可能导致性能风险, 所以我都是禁止团队试用 golang orm 的”

    这一点可以举例说明:有哪些不确定性可能导致性能风险吗

    我现在在公司用的就是 GORM ,想了解一下
    knva
    knva
    Jul 17, 2024
    88
    go 的 sql set 0 的问题太带劲了
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    89
    @fregie 你满意就好
    boqiqita
    boqiqita
    Jul 17, 2024
    90
    幸好不会用 java 、C#、C 、C++
    XyIsMy
    XyIsMy
    Jul 17, 2024
    91
    @zzhaolei @lesismal grom 可以设置 Logger level 在开发过程中就可以看到执行的 sql ,有问题能直接发现。gorm 也有 raw sql 模式可以直接用。
    是在使用 GROM 中踩了哪些坑么。如果有坑的话,我需要重新考虑下要不要用 gorm
    picone
    picone
    Jul 17, 2024
    92
    Go 使用 json.RawMessage 也可以达到你说的效果,不会变成 base64
    zzhaolei
    zzhaolei
    Jul 17, 2024
    93
    @XyIsMy 我是这么用的。

    我就是好奇,这些人张嘴闭嘴就是 ORM 有不确定性,到底有什么不确定性,自己测试过?还是踩过坑?还是说嘴一张一闭反正我不管,ORM 就是有性能问题?

    我之前进行过性能测试,如果 GORM 那些事务什么的全都关了,是会比原生 SQL 慢一些,但是没有慢特别多。至今没有踩过什么坑。
    james122333
    james122333
    Jul 17, 2024
    94
    @zzhaolei

    orm 本身没有不确定性 本质还是产生 query string 传参 orm 的不确定性在於框架的实现 太过细节的框架从另外角度讲是坑
    gorm 确实是慢没错 更何况就是要用事务
    我离职了再写一个比较好的自己用
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    95
    各位,我比对了下,[]interface{}没有被 json.Marshal 出正确的数值和类型,是与我用的 go-mysql-driver 版本有关。

    1.6.0 版本是出现了与我预测不同的结果。1.8 版本出现了预测的结果

    json.Marshal 可能与本次贴文无直接关系。

    另外,我觉得问题出自 json.Marshal 是从这个 sof 链接中的评论得到的错误推论,的确有迷惑性( https://stackoverflow.com/questions/34089750/marshal-byte-to-json-giving-a-strange-string)


    ```
    This is because some idiot Millennial at Google decided it. Breaking the behaviour the RFC their JSON impl claims to follow defines. Check stackoverflow.com/a/78662958/3768429 for details.
    ```

    该文指出 json.Marshal 处理 uint8[]时,错误输出了文字, 验证代码如下
    ```
    func main() {
    var x = []uint8{1, 2, 3, 4, 5, 6}
    var y = []int8{1, 2, 3, 4, 5, 6}
    xBytes, err := json.Marshal(x)
    if err != nil {
    panic(err)
    }
    yBytes, err := json.Marshal(y)
    if err != nil {
    panic(err)
    }
    fmt.Println(fmt.Sprintf("uint8 %s, int8: %s", string(xBytes), string(yBytes)))
    }
    ```
    输出的结果为
    ```
    uint8 "AQIDBAUG", int8: [1,2,3,4,5,6]
    ```

    https://go.dev/play/p/KGNG6voRuDk
    sagaxu
    sagaxu
    Jul 17, 2024
    96
    @zzhaolei @XyIsMy

    ORM 的不确定性往往不是出自 ORM 本身,而是使用者的不确定性,大部分人只是会用,并不全面了解,有些时候会遇到令人惊讶的特性,其中不少人会专门写踩坑博文。
    qW7bo2FbzbC0
    qW7bo2FbzbC0
    OP
    Jul 17, 2024
    97
    @james122333 您是对的,这的确和 json.Marshal 没关系,是 go-mysql-driver 的问题。

    https://github.com/go-sql-driver/mysql/pull/1424
    james122333
    james122333
    Jul 17, 2024
    98
    @qW7bo2FbzbC0

    vczyh 先讲这问题的 后面才看到 你要先感谢他
    james122333
    james122333
    Jul 17, 2024 via Android
    99
    @qW7bo2FbzbC0

    我有跳转过去 go 底层看就是 基本类型应该都有函盖才对 所以推测 driver 问题 不过没验过 对照一下 vczyh 的说明应该是这样
    ClericPy
    ClericPy
    Jul 17, 2024
    100
    以前是用别的语言的吧,我记得有个库可以用比原生的优雅一点,不习惯的话要不要问问别人怎么用的再来吐槽

    话说对于 JSON 解析如果没啥特殊需求,大多数语言都有 jmespath 的分支吧,以前用 py 的版本发现性能秒杀同类 jsonpath/objectpath 而且语法也简单,没必要自己硬抠嵌套结构,json-handler 一开直接提取路径了
    1  2  
    ❮ ❯
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1373 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 164ms · UTC 22:32 · PVG 06:32 · LAX 14:32 · JFK 17:32
    ♥ Do have faith in what you're doing.