如何从 Go 中解释 PostgreSQL 错误消息?
How do I interpret PostgreSQL error messages from within Go?
我如何解析 SQL 约束错误,特别是由 Go 中的 UNIQUE
、FOREIGN KEY
、NOT NULL
、ON DELETE RESTRICT
等约束引起的错误?
例如插入一个可能具有相同电子邮件的新用户,该电子邮件在数据库中定义为 UNIQUE
字段。 Go 中解析约束错误,return 浏览器客户端错误。
有关如何解释来自 github.com/lib/pq 的错误的信息,请参阅 http://godoc.org/github.com/lib/pq#Error.
这是我的做法:
// ShowError sends an appropriate error message.
func ShowError(w http.ResponseWriter, r *http.Request, err error) {
switch e := err.(type) {
case *pq.Error:
switch e.Code {
case "23502":
// not-null constraint violation
http.Error(w, fmt.Sprint("Some required data was left out:\n\n", e.Message), http.StatusForbidden)
return
case "23503":
// foreign key violation
switch r.Method {
case "DELETE":
http.Error(w, fmt.Sprint("This record can’t be deleted because another record refers to it:\n\n", e.Detail), http.StatusForbidden)
return
}
case "23505":
// unique constraint violation
http.Error(w, fmt.Sprint("This record contains duplicated data that conflicts with what is already in the database:\n\n", e.Detail), http.StatusForbidden)
return
case "23514":
// check constraint violation
http.Error(w, fmt.Sprint("This record contains inconsistent or out-of-range data:\n\n", e.Message), http.StatusForbidden)
return
default:
msg := e.Message
if d := e.Detail; d != "" {
msg += "\n\n" + d
}
if h := e.Hint; h != "" {
msg += "\n\n" + h
}
http.Error(w, msg, http.StatusInternalServerError)
return
}
case *strconv.NumError:
http.Error(w, fmt.Sprintf(`"%s" is not a valid number.`, e.Num), http.StatusBadRequest)
return
default:
switch err {
case sql.ErrNoRows:
http.NotFound(w, r)
return
}
}
http.Error(w, err.Error(), http.StatusInternalServerError)
}
我如何解析 SQL 约束错误,特别是由 Go 中的 UNIQUE
、FOREIGN KEY
、NOT NULL
、ON DELETE RESTRICT
等约束引起的错误?
例如插入一个可能具有相同电子邮件的新用户,该电子邮件在数据库中定义为 UNIQUE
字段。 Go 中解析约束错误,return 浏览器客户端错误。
有关如何解释来自 github.com/lib/pq 的错误的信息,请参阅 http://godoc.org/github.com/lib/pq#Error.
这是我的做法:
// ShowError sends an appropriate error message.
func ShowError(w http.ResponseWriter, r *http.Request, err error) {
switch e := err.(type) {
case *pq.Error:
switch e.Code {
case "23502":
// not-null constraint violation
http.Error(w, fmt.Sprint("Some required data was left out:\n\n", e.Message), http.StatusForbidden)
return
case "23503":
// foreign key violation
switch r.Method {
case "DELETE":
http.Error(w, fmt.Sprint("This record can’t be deleted because another record refers to it:\n\n", e.Detail), http.StatusForbidden)
return
}
case "23505":
// unique constraint violation
http.Error(w, fmt.Sprint("This record contains duplicated data that conflicts with what is already in the database:\n\n", e.Detail), http.StatusForbidden)
return
case "23514":
// check constraint violation
http.Error(w, fmt.Sprint("This record contains inconsistent or out-of-range data:\n\n", e.Message), http.StatusForbidden)
return
default:
msg := e.Message
if d := e.Detail; d != "" {
msg += "\n\n" + d
}
if h := e.Hint; h != "" {
msg += "\n\n" + h
}
http.Error(w, msg, http.StatusInternalServerError)
return
}
case *strconv.NumError:
http.Error(w, fmt.Sprintf(`"%s" is not a valid number.`, e.Num), http.StatusBadRequest)
return
default:
switch err {
case sql.ErrNoRows:
http.NotFound(w, r)
return
}
}
http.Error(w, err.Error(), http.StatusInternalServerError)
}