[已解决]Golang向Postgres数据库插入数据时遇到的问题
[已解决]Golang向Postgres数据库插入数据时遇到的问题 大家好, 当我想插入数据库时遇到了一个错误。
我的插入方法:
func RegisterUser(db *sql.DB, w http.ResponseWriter, r *http.Request) {
user := model.User{}
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&user); err != nil {
respondError(w, http.StatusBadRequest, err.Error())
return
}
defer r.Body.Close()
sqlStatement := `
INSERT INTO users (id, name, avatar, mobile, birth_day, identify, cart, credit, type, password)
VALUES ($1, $2, $3, $4, $5, &6, &7, &8, &9)
RETURNING id`
stmt, err := db.Prepare(sqlStatement)
fmt.Println("******************here2", user)
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
var userID int
if err := stmt.QueryRow(sqlStatement, user.ID, user.Name, user.Avatar, user.Mobile, user.BirthDay, user.Identify, user.Cart, user.Credit, user.Type, user.Password); err != nil {
//respondError(w, http.StatusInternalServerError, err.Error())
log.Fatal(err)
return
}
fmt.Println("New record ID is:", userID)
respondJSON(w, http.StatusCreated, user)
}
这是错误日志: http: panic serving [::1]:39878: runtime error: invalid memory address or nil pointer dereference goroutine 18 [running]:
更多解释: 我有一个包含以下字段的 User 结构体:
type User struct {
Base
Name string `json:"name"`
Avatar string `json:"avatar"`
Email string `db:"unique;not null";json:"email"`
Mobile string `json:"mobile"`
BirthDay string `json:"birthday"`
Identify string `json:"identify"`
Cart string `json:"cart"`
Credit string `json:"credit"`
Type int `json:"type"`
Password string `json:"password"`
Permissions string
}
User 结构体中的 Base 是:
import (
"github.com/jinzhu/gorm"
uuid "github.com/satori/go.uuid"
)
type Base struct {
ID uuid.UUID `db:"type:uuid;primary_key;not null;" json:"-"`
}
func (base *Base) BeforeCreate(scope *gorm.Scope) error {
uuid, err := uuid.NewV4()
if err != nil {
return err
}
return scope.SetColumn("ID", uuid)
}
这个 Base 是为每个 User 记录生成 UUID 的。 但我在这个部分遇到了错误:
stmt, err := db.Prepare(sqlStatement)
fmt.Println("******************here2", user)
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
可以请帮我修复这个部分以将数据插入数据库吗?
更多关于[已解决]Golang向Postgres数据库插入数据时遇到的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
在我的 app.go 文件中,我关闭了数据库连接。这导致了应用程序崩溃。我移除了那行代码,不再关闭连接。现在一切正常了。
func RegisterUser(db *sql.DB, w http.ResponseWriter, r *http.Request) {
user := model.User{}
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&user); err != nil {
respondError(w, http.StatusBadRequest, err.Error())
return
}
defer r.Body.Close()
stmt, err := db.Prepare("INSERT INTO users(id,name,avatar,mobile, email,birth_day, identify, cart, credit, password, type) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);")
fmt.Println(db)
if err != nil {
fmt.Println("not work")
panic(err)
}
uuid, err := uuid.NewV4()
res, err := stmt.Exec(uuid, user.Name, user.Avatar, user.Mobile, user.Email, user.BirthDay, user.Identify, user.Cart, user.Credit, user.Password, user.Type)
fmt.Println(res.LastInsertId())
//respondJSON(w, http.StatusCreated, user)
}
这是我的用户注册方法,用于将用户插入数据库。希望这对其他人有所帮助。
更多关于[已解决]Golang向Postgres数据库插入数据时遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在我检查时,db 是 nil。在此之前,我使用了 gorm 和一些 Init 方法以及 App 结构体。经过一些更改后,我的代码现在在 app.go 中是这样的:
type App struct {
Router *mux.Router
DB *sql.DB
}
在 Initialize 方法中,我有以下代码:
// App initialize with predefined configuration
func (a *App) Initialize(config *config.Config) {
dbURI := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s",
config.DB.Host,
config.DB.Port,
config.DB.User,
config.DB.DbName,
config.DB.Password)
db, err := sql.Open(config.DB.Dialect, dbURI)
if err != nil {
log.Fatal("Could not connect database")
}
defer db.Close()
err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("Successfully connected!")
//a.DB = model.DBMigrate(db)
a.Router = mux.NewRouter()
a.setRouters()
}
如上代码所示,当我使用 gorm 时,a.DB 被赋予了一些值,但现在我刚刚注释掉了这一行。我必须为它设置什么值?因为在我检查时 a.DB 是 nil,我将它传递给 register 方法并收到一个错误。
根据你的代码分析,主要问题出现在以下几个方面:
1. SQL语句占位符数量不匹配
你的SQL语句有10个字段,但只有9个占位符($1到$9)
2. 错误的占位符语法
使用了 &6, &7, &8, &9 而不是 $6, $7, $8, $9, $10
3. UUID处理问题
Base 结构体使用了GORM的钩子,但你的代码使用的是标准库的 database/sql
修复后的代码:
func RegisterUser(db *sql.DB, w http.ResponseWriter, r *http.Request) {
user := model.User{}
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&user); err != nil {
respondError(w, http.StatusBadRequest, err.Error())
return
}
defer r.Body.Close()
// 生成UUID(因为不使用GORM的BeforeCreate钩子)
user.ID = uuid.NewV4()
sqlStatement := `
INSERT INTO users (id, name, avatar, mobile, birth_day, identify, cart, credit, type, password)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING id`
var userID string
// 直接使用QueryRow,不需要Prepare
err := db.QueryRow(
sqlStatement,
user.ID, // $1
user.Name, // $2
user.Avatar, // $3
user.Mobile, // $4
user.BirthDay,// $5
user.Identify,// $6
user.Cart, // $7
user.Credit, // $8
user.Type, // $9
user.Password,// $10
).Scan(&userID)
if err != nil {
log.Printf("插入失败: %v", err)
respondError(w, http.StatusInternalServerError, err.Error())
return
}
fmt.Println("New record ID is:", userID)
respondJSON(w, http.StatusCreated, user)
}
或者使用Prepare的版本:
func RegisterUser(db *sql.DB, w http.ResponseWriter, r *http.Request) {
user := model.User{}
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&user); err != nil {
respondError(w, http.StatusBadRequest, err.Error())
return
}
defer r.Body.Close()
// 生成UUID
user.ID = uuid.NewV4()
sqlStatement := `
INSERT INTO users (id, name, avatar, mobile, birth_day, identify, cart, credit, type, password)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING id`
stmt, err := db.Prepare(sqlStatement)
if err != nil {
log.Printf("准备语句失败: %v", err)
respondError(w, http.StatusInternalServerError, err.Error())
return
}
defer stmt.Close()
var userID string
err = stmt.QueryRow(
user.ID,
user.Name,
user.Avatar,
user.Mobile,
user.BirthDay,
user.Identify,
user.Cart,
user.Credit,
user.Type,
user.Password,
).Scan(&userID)
if err != nil {
log.Printf("插入失败: %v", err)
respondError(w, http.StatusInternalServerError, err.Error())
return
}
fmt.Println("New record ID is:", userID)
respondJSON(w, http.StatusCreated, user)
}
关键修复点:
- 占位符修正:
$1到$10共10个占位符 - UUID生成:手动调用
uuid.NewV4()生成ID - 错误处理:使用
log.Printf而不是log.Fatal,避免服务崩溃 - Scan方法:使用
.Scan(&userID)获取返回的ID
注意:由于你使用了标准库的 database/sql 而不是GORM,BeforeCreate 钩子不会自动执行,需要手动生成UUID。

