如何在 Go 中将 table 数据写入嵌套结构

How to write table data into a nested struct in Go

总结

我正在尝试将多个 postgres 表中的数据写入嵌套的 Go 结构,目的是返回单个 json 对我的网络应用程序中的 GET 请求的响应。

问题

  1. 从 Go 最佳实践的角度来看,我声明嵌套结构的方式是否合理,或者我是否应该避免使用这种方法并以其他方式进行?
  2. 我在步骤 3 中做错了什么以阻止我的代码工作? (恐怕答案是'everything')

到目前为止我得到了什么

  1. 我已经声明了我的结构结构
type MainObject struct {

    SubObjects []struct {
        SpecificDetail string `json:"specific-detail"`
                           }  `json:"sub-object"`

    ...(other []structs)...
}
  1. 我已经从表中检索了行
func getMainObjectHandler(w http.ResponseWriter, r *http.Request) {
    
    ...(database connnection)...
    
    MainObjectID := r.URL.Query().Get("moid")
    if MainObjectID != "null" {
        NewMainObject := MainObject{}
        SubObjectDetail_rows, err := db.Query("SELECT specific_detail from the_table WHERE moid= '" + MainObjectID + "'")
        if err != nil {
            log.Fatalf("could not execute query: %v", err)
        }
        
        ...(other db.Query rows)...
  1. 我已经尝试(但失败了)将行数据构建到结构中。
        for SubObjectDetail_rows.Next() {
            SpecificDetail := NewMainObject.SubObject.SpecificDetail{}
            SubObjectDetail_rows.Scan(&SpecificDetail)
            SubObject = append(SubObject, SpecificDetail)
        }
        NewMainObject = append(MainObject, SubObject)
        defer persona_rows.Close()
  1. 最后,我设置了 Marshal 并写入。
        NMOListBytes, err := json.Marshal(NewMainObject)
        if err != nil {
            fmt.Println(fmt.Errorf("Error: %v", err))
            w.WriteHeader(http.StatusInternalServerError)
            return
        }
        w.Write(NMOListBytes)

首先,请在创建 SQL 查询时使用占位符以避免注入:

// db.Query("SELECT specific_detail from the_table WHERE moid= '" + MainObjectID + "'")  // not this
db.Query("SELECT specific_detail from the_table WHERE moid=?", MainObjectID)

除非您使用 GORM 之类的框架,否则您不能 Scan() 到单个结构值中。 来自 the docs:

Scan copies the columns in the current row into the values pointed at by dest. The number of values in dest must be the same as the number of columns in Rows.

看起来您正在从数据库查询中提取 JSON,因为您只查询一列,所以您可能想要:

var bs []byte // get raw JSON bytes

err = SubObjectDetail_rows.Scan(&bs) 
if err != nil { /* always check errors */ }

然后将它们解组到您的结构中:

err = json.Unmarshal(bs, &SpecificDetail)
if err != nil { /* ... */ }