【问题标题】:How to Insert values from Postman (json type) to Postgres using Gorm (go struct)如何使用 Gorm(go struct)将 Postman(json 类型)中的值插入 Postgres
【发布时间】:2020-07-13 14:05:33
【问题描述】:

我正在尝试编写一些专注于员工管理的简单 CRUD,但在这一点上我有点困惑,所以我应该如何使用结构属性 json:...gorm: 来声明特定的数据类型和约束Postman 以 json 格式发送的新数据库表和特定值。你在使用 Go-Gorm 吗?

//db file
package tiposDocumentos

import (
    "bitbucket.org/username/repositoryname/db"
    "bitbucket.org/username/repositoryname/models"
)

// Inserta un nuevo tipo de documento en la base de datos.
func InsertTipoDocumento(tp models.TiposDocumentos) (bool, error) {
    db.PsqlDb.AutoMigrate(&tp)
    if db.PsqlDb.NewRecord(tp) {
        err := db.PsqlDb.Create(&tp)
        if err != nil {
            return false, nil
        }
    } else {
        return false, errors.New("clave primaria se encuentra en uso")
    }

    return true, nil
}
package models
    
type TiposDocumentos struct {
        TdoCodigo       string  `json:"tdo_codigo" gorm:"column:tdo_codigo;type:varchar(3);PRIMARY_KEY;AUTO_INCREMENT:false"`
        TdoDescripcion  string  `json:"tdo_descripcion" gorm:"column:tdo_descripcion;type:varchar(50)"`
        TdoCodigoAfip   string  `json:"tdo_codigo_afip" gorm:"column:tdo_codigo_afip;type:varchar(10)"`
}
package routers

import (
    "bitbucket.org/username/repositoryname/db/tiposDocumentos"
    "bitbucket.org/username/repositoryname/models"
    "encoding/json"
    "fmt"
    "net/http"
)

var (
    tp models.TiposDocumentos
)

// Valida registro recibido y lo inserta en la base de datos.
func PostTiposDocuemntos(w http.ResponseWriter, r *http.Request) {
    err := json.NewDecoder(r.Body).Decode(&tp)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    estado, err := tiposDocumentos.InsertTipoDocumento(tp)
    if estado == false {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    w.WriteHeader(http.StatusCreated)
}

此时,程序从 Postman 发出请求后,成功创建表及其规格并检索代码 201,但该记录未插入表中。 从 pgAdmin4 查看

谢谢☻

在数据库中成功插入新记录后出错:

2020/07/13 12:43:28 http: panic serving 127.0.0.1:64546: runtime error: invalid memory address or nil pointer dereference
goroutine 36 [running]:
net/http.(*conn).serve.func1(0xc000230d20)
        C:/Go/src/net/http/server.go:1772 +0x140
panic(0x8085e0, 0xbb5e20)
        C:/Go/src/runtime/panic.go:975 +0x3f1
bitbucket.org/emanuelvald/gestion_personal/routers.PostTiposDocuemntos(0x912c20, 0xc00005e000, 0xc000058200)
        C:/Projects/Go/src/bitbucket.org/emanuelvald/gestion_personal/routers/tiposDocumentos.go:44 +0x151
net/http.HandlerFunc.ServeHTTP(0x893498, 0x912c20, 0xc00005e000, 0xc000058200)
        C:/Go/src/net/http/server.go:2012 +0x4b
github.com/gorilla/mux.(*Router).ServeHTTP(0xc00022a0c0, 0x912c20, 0xc00005e000, 0xc000058000)
        C:/Projects/Go/src/github.com/gorilla/mux/mux.go:210 +0xe9
net/http.serverHandler.ServeHTTP(0xc000270000, 0x912c20, 0xc00005e000, 0xc000058000)
        C:/Go/src/net/http/server.go:2807 +0xaa
net/http.(*conn).serve(0xc000230d20, 0x9137a0, 0xc000038080)
        C:/Go/src/net/http/server.go:1895 +0x873
created by net/http.(*Server).Serve
        C:/Go/src/net/http/server.go:2933 +0x363

【问题讨论】:

  • 当这个if db.PsqlDb.NewRecord(tp) { 不满意时,您将返回true, nil,然后您将其解释为“一切顺利”,即使它显然没有。先修复逻辑。
  • 我修复了这个问题,NewRecord 函数返回 false,好像使用了主键但表为空!!!
  • 将恐慌的完整堆栈跟踪添加到问题中,我将指出导致崩溃的确切文件和行。但是,如果我不得不猜测,gorm Create 返回 *DB 实例而不是错误,所以 err 变量始终是非零 *DB,因此 if err != nil { 总是满足...然后在该分支中,您返回false, nil,随后您让调用者在该nil 错误值上调用err.Error(),然后繁荣!
  • 检查 gorm 错误的正确方法是检查 *DB 实例的 Error 字段。即err := db.Create(&tp).Error,然后如果err不是nil,则需要将其返回给调用者return false, err
  • 堆栈跟踪显示恐慌的根源来自文件...routers/tiposDocumentos.go 中的routers.PostTiposDocuemntos 函数,位于44 行。

标签: postgresql go go-gorm


【解决方案1】:

考虑一下当 err 不是 nil 时会发生什么:

 if err != nil {
     return false, nil
 }

然后你这样做:

estado, err := tiposDocumentos.InsertTipoDocumento(tp)
if estado == false {
    http.Error(w, err.Error(), http.StatusBadRequest)
    return
}

所以,estado 是 false,然后你尝试访问 err.Error(),但 errnil,所以你得到了一个

invalid memory address or nil pointer dereference

您可能只需要这样做:

 if err != nil {
     return false, err
 }

然后做:

if err != nil {
    http.Error(w, err.Error(), http.StatusBadRequest)
    return
}

【讨论】:

  • 非常感谢 Dave,我在您的帮助下修复了我的代码。现在我可以在我的 CRUD 项目中插入新记录并且我不会检索错误。再见!!!
  • @YoungAlCapone 如果可能,请尝试遵循指南:stackoverflow.com/help/someone-answers
  • 对不起,我忘了接受你的回答。再次感谢:)
猜你喜欢
  • 2020-05-26
  • 1970-01-01
  • 1970-01-01
  • 2018-01-08
  • 1970-01-01
  • 2022-12-17
  • 1970-01-01
  • 2021-12-22
  • 2020-01-06
相关资源
最近更新 更多