【问题标题】:Return postgres errors in api response在 api 响应中返回 postgres 错误
【发布时间】:2021-01-08 06:09:18
【问题描述】:

我的代码中有两个简单的 api 方法。端点/api/user/create 的方法创建用户。字段 username 是唯一的。当我尝试使用数据库中已存在的相同用户名创建用户时,控制台中出现错误:

(/home/andrej/go/src/go_contacts/models/users.go:19) 
[2020-12-23 22:03:10]  pq: duplicate key value violates unique constraint "users_username_key"

我想显示此错误以响应用户,或者以某种方式识别我的代码中的错误类型,以便为用户显示不同的错误消息。我只知道如果我有错误user 返回我 id=0。但这对用户来说似乎不是一个好消息。

main.go

package main

import (
    "fmt"
    "go_contacts/controllers"
    "net/http"
    "os"

    "github.com/gorilla/mux"
    "github.com/joho/godotenv"
)

func main() {
    godotenv.Load(".env")


    router := mux.NewRouter()
    router.HandleFunc("/", controllers.ReturnHello).Methods("GET")
    router.HandleFunc("/api/user/create", controllers.CreateUser).Methods("POST")

    port := os.Getenv("PORT")
    if port == "" {
        port = "8000"
    }

    err := http.ListenAndServe(":"+port, router)
    if err != nil {
        fmt.Print(err)
    }
}

models.go 带有用户结构:

package models

import (
    u "go_contacts/utils"

    "github.com/jinzhu/gorm"
)

// User base model
type User struct {
    gorm.Model
    Username string `json:"username" gorm:"unique"`
    Password string `json:"password"`
    Email    string `json:"email"`
}

// Create new user
func (user *User) Create() map[string]interface{} {
    GetDB().Create(user)

    if user.ID <= 0 {
        return u.Message(false, "Failed to create user, connection error.")
    }

    response := u.Message(true, "Account has been created")
    response["user"] = user
    return response
}

【问题讨论】:

  • 你有没有考虑检查Create返回的错误? (例如result := GetDB().Create(user); if result.Error != nil {...)文档herehere 中的更多信息。
  • @Brits 谢谢。正是我要找的

标签: postgresql go go-gorm


【解决方案1】:

至于 pq v1.5.2 和 gorm v1.9.12

首先需要判断create方法调用是否返回错误。像这样

err := GetDB().Create(user).Error
if err != nil {
    // code to handle error
}

然后 pq 包具有映射到 postgres 服务器错误的特殊类型。它包含可以帮助您识别错误严重程度的字段,它的代码,与错误相关的表格等。

psql 字段标识符的完整列表可在此处找到

错误和通知消息字段

https://www.postgresql.org/docs/current/protocol-error-fields.html

为了解决您的问题,我们可以使用字段

Code

这是错误代码的字符串类型表示。但首先,我们需要转换错误并检查类型转换是否成功。像这样

err := GetDB().Create(user).Error
if err != nil {
    pqErr, ok := err.(pq.Error)
    if !ok {
        log.Fatal(err)
    }

    // code to handle specific error code
}

错误代码列表可以在官方postgresql文档https://www.postgresql.org/docs/9.3/errcodes-appendix.html中找到

和 pq 库中 github.com/lib/pq/error.go 中错误的实际 go pq 特定映射

最后我们可以通过代码处理重复的错误

err := GetDB().Create(user).Error
if err != nil {
    pqErr, ok := err.(pq.Error)
    if !ok {
        log.Fatal(err)
    }

    // note that type casting here is redundant and used for showing specific 
    // string type from pq library
    if pqErr.Code == pq.ErrorCode("23505") { // 23505 is unique_violation error code for psql
        // now you can create error and write it to a message to return it for 
        // a client
    }
}

【讨论】:

    【解决方案2】:

    根据 cmets,gorm 提供了从 Create record 函数对 database errors 的访问权限,如下所示:

    result := GetDB().Create(user)
    if result.Error != nil {
       // Do something with the error
    }
    

    请注意,检查错误字符串可能会使您的应用程序数据库特定(但这对您来说可能不是问题)。 this question 的答案可能会提供进一步的帮助。

    【讨论】:

      猜你喜欢
      • 2017-02-17
      • 1970-01-01
      • 1970-01-01
      • 2016-10-29
      • 2013-06-09
      • 2019-05-26
      • 2020-08-08
      • 2021-12-20
      • 1970-01-01
      相关资源
      最近更新 更多