【问题标题】:Storing Sql result sets in a nested struct and omit if empty将 Sql 结果集存储在嵌套结构中,如果为空则省略
【发布时间】:2015-11-01 11:04:02
【问题描述】:

我正在尝试将 SQL 查询数据集存储在结构中并以 JSON 格式显示。我几乎做到了。现在的问题是,如果嵌套结构的结果集为空,那么我不想显示它。

同样的问题specified here,但是在扫描时使用指针以恐慌结束可能是因为我正在使用&user.Profile.Firstname

2015/11/01 16:42:16 恐慌恢复 -> 运行时错误:无效的内存地址或 nil 指针取消引用

如果我删除指针,那么一切正常,只剩下空字段。我很困惑如何实现这一目标。

package main

import (
    "database/sql"
    "github.com/gin-gonic/gin"
    _ "github.com/go-sql-driver/mysql"
    "log"
)

type User struct {
    Id       int64
    Username string
    Email    string
    Profile  Profile `json:",omitempty"`
}

type Profile struct {
    Id        int64  `json:",omitempty"`
    UserId    int64  `json:",omitempty"`
    Firstname *string `json:",omitempty"`
    Lastname  *string `json:",omitempty"`
}

var DB *sql.DB

func checkErr(err error, msg string) {
    if err != nil {
        log.Fatal(msg, err)
    }
}

func main() {
    DB, _ = sql.Open("mysql", "username:secrect@/database")
    defer DB.Close()

    r := gin.Default()
    v1 := r.Group("api/v1/")
    {
        v1.GET("users", GetUsers)
    }
    r.Run(":8080")
}


func GetUsers(c *gin.Context) {
    stmt, err := DB.Query("Select users.id, username , email , firstname , lastname from users left join profiles on users.id = profiles.user_id ")
    if err != nil {
        panic(err.Error())
    }
    defer stmt.Close()

    users := []User{}

    for stmt.Next() {
        var user User
        err := stmt.Scan(&user.Id, &user.Username, &user.Email, &user.Profile.Firstname, &user.Profile.Lastname)
        if err != nil {
            panic(err.Error())
        }

        users = append(users, user)
    }

    c.JSON(200, &users)
}

输出:

{
  "Id": 1,
  "Username": "test1",
  "Email": "test1@example.com",
  "Profile": {
    "Firstname": "John",
    "Lastname": "Doe"
  }
},
{
  "Id": 2,
  "Username": "test2",
  "Email": "test2@example.com",
  "Profile": {
  }
},

【问题讨论】:

    标签: mysql go


    【解决方案1】:

    假设gin在幕后使用encoding/json,如果你想省略一个空的Profile,我相信你需要它作为User中的指针:

    type User struct {
        ....
        Profile *Profile `json:",omitempty"`
    }
    

    注意documentation

    “omitempty”选项指定如果字段具有空值(定义为 false、0、nil 指针、nil 接口值以及任何空数组、切片、映射、或字符串。

    并不是说结构的零值会被检测到。

    这会让您在从数据库中扫描数据时遇到一些问题。您可以声明一个Profile,扫描到它,与零配置文件进行比较,如果它有数据,则将其分配给User

    var user User
    var profile Profile
    _ = stmt.Scan(&user.Id, &user.Username, &user.Email, &profile.Firstname, &profile.Lastname)
    if profile != Profile{} {
        user.Profile = &profile
    }
    

    我怀疑这不是最优雅的解决方案,但我希望这是正确的方向。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      • 2023-02-20
      • 2018-04-14
      • 2022-07-25
      • 2015-02-07
      相关资源
      最近更新 更多