doumaque6551 2015-11-01 11:04
浏览 55
已采纳

将SQL结果集存储在嵌套结构中,如果为空则省略

I am trying to store SQL query dataset in a struct and display in JSON. I have almost done it. Now the problem is if the result set of nested structs is empty then I would not like to display it.

Same problem specified here but using a pointer ends in a panic when scanning may be because I am using &user.Profile.Firstname

2015/11/01 16:42:16 Panic recovery -> runtime error: invalid memory address or nil pointer dereference

If I remove the pointer then everything works fine just the empty field remains. I am confused how to achieve this.

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)
}

Output:

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

1条回答 默认 最新

  • dongzhimeng2464 2018-02-26 19:28
    关注

    Assuming gin uses encoding/json under the covers, if you want to omit an empty Profile, I believe you need it to be a pointer in User:

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

    Note the documentation:

    The "omitempty" option specifies that the field should be omitted from the encoding if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.

    It doesn't say that the zero value of a struct will be detected.

    That will leave you with some issues scanning your data from the db. You could declare a Profile, scan into it, compare to the zero profile and assign it to the User if it has data:

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

    I suspect that's not the most elegant solution, but I hope it's the right direction.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 phython如何实现以下功能?查找同一用户名的消费金额合并—
  • ¥15 孟德尔随机化怎样画共定位分析图
  • ¥18 模拟电路问题解答有偿速度
  • ¥15 CST仿真别人的模型结果仿真结果S参数完全不对
  • ¥15 误删注册表文件致win10无法开启
  • ¥15 请问在阿里云服务器中怎么利用数据库制作网站
  • ¥60 ESP32怎么烧录自启动程序
  • ¥50 html2canvas超出滚动条不显示
  • ¥15 java业务性能问题求解(sql,业务设计相关)
  • ¥15 52810 尾椎c三个a 写蓝牙地址