绕过Go中的sql null值问题

Jos*_*h B 8 go

我想使用Go为广泛使用空值的现有数据库创建API.Go不会将空值扫描为空字符串(或等效字符串),因此我需要实现一种解决方法.

我发现的变通方法让我不满意.事实上,由于这个问题,我一直在寻找一种动态的语言,但Go有一定的吸引力,如果可能的话我想坚持下去.以下是不满足的解决方法:

  1. 不要在数据库中使用空值.不适合,因为数据库是预先存在的,我没有自由干涉其结构.数据库比我的应用程序更重要,而不是相反.
  2. 在SQL查询中,使用COALESCE,ISNULL等在数据到达我的应用程序之前将空值转换为空字符串(或等效).不适合,因为有许多字段和许多表.除了一些显而易见的(主键,姓)之外,我不确定哪些字段可以依赖不给我一个空值,所以我会在任何地方防御性地混乱我的SQL查询.
  3. 在将它们置于目标类型之前,使用sql.NullString,sql.NullInt64,sql.NullFloat64等将空值转换为空字符串(或等效项)作为中间步骤.这会遇到与上面相同的问题,只是我混乱了我的Go代码而不是我的SQL查询.
  4. 使用*指针和[]字节的组合,将每个项目扫描到内存位置,而不将其提交到特定类型(除[] byte之外),然后以某种方式处理原始数据.但要对数据做一些有意义的事情,你必须将它转换为更有用的东西,然后你回到sql.Nullstring或者如果x == nil {handle it},这又是根据具体情况发生的我需要处理的任何领域.所以,我们再一次看到杂乱,杂乱,容易出错的代码,我一直在重复自己,而不是在编码时干掉.
  5. 请向Go ORM库寻求帮助.嗯,我做到了,但令我惊讶的是,他们都没有解决这个问题.
  6. 创建我自己的帮助程序包,将所有空字符串转换为"",将null整数转换为0,将null浮点数转换为0.00,将null bools转换为false等,并使其成为从sql驱动程序扫描的过程的一部分,从而产生常规,普通字符串,整数,浮点数和布尔值.

    不幸的是,如果6是解决方案,我没有专业知识.我怀疑解决方案会涉及"如果要扫描的项目的预期类型是字符串,使其成为sql.NullString并从中提取空字符串.但是如果要扫描的项目是int,使它成为NullInt64并从中获得零.但是如果...(等)"

有什么我错过了吗?谢谢.

Jos*_*h B 7

使用 sql 扫描目标变量的指针使数据能够被扫描、处理(取决于检查是否 != nil)并编组到 json,从 API 发送出去,不必放入数百个 sql .Nullstring、sql.Nullfloat64 等无处不在。空值被奇迹般地保存下来并通过编组的 json 发送出去。(见底部的父名)。在另一端,客户端可以使用 javascript 中的空值,这样可以更好地处理它们。

func queryToJson(db *sql.DB) []byte {
    rows, err := db.Query(
      "select mothername, fathername, surname from fams" +
      "where surname = ?", "Nullfather"
    )
    defer rows.Close()

    type record struct {
        Mname, Fname, Surname *string  // the key: use pointers
    }
    records := []record{}

    for rows.Next() {
        var r record
        err := rows.Scan(r.Mname, r.Fname, r.Surname) // no need for "&"
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(r)
        records = append(records, r)
    }
    j, err := json.Marshal(records)
    if err != nil {
        log.Fatal(err)
    }
    return j
}
j := queryToJson(db)
fmt.Println(string(j)) // [{"Mothername":"Mary", "Fathername":null, "Surname":"Nullfather"}]
Run Code Online (Sandbox Code Playgroud)