使用db.QueryRow时触发Golang运行时空指针引用错误求助
解决Go TodoList项目中的空指针运行时错误
问题根源分析
从错误栈和代码来看,空指针错误由两个核心问题导致:
1. 数据库连接变量被遮蔽且提前关闭
在db.go的InitDatabase函数中,使用:=声明了局部变量Conn,直接覆盖了全局定义的var Conn *pgx.Conn,导致全局Conn始终为nil。同时,函数内的defer Conn.Close()会在函数执行完毕后立即关闭连接,后续请求无法获取有效数据库连接。
2. Task指针未初始化
在controller.go的GetTasks函数中,response是未初始化的*Task类型指针,直接访问&response.Title会触发空指针解引用错误。
修复方案
修复数据库连接问题(db.go)
修改InitDatabase函数,避免变量遮蔽,移除提前关闭连接的逻辑:
package db import ( "os" "fmt" "context" "github.com/jackc/pgx/v4" "github.com/fishkaoff/todoList/internal/config" ) var Conn *pgx.Conn func InitDatabase(config config.Config) { var err error // 使用=赋值给全局变量,而非:=创建局部变量 Conn, err = pgx.Connect(context.Background(), config.DBUrl) if err != nil { fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err) os.Exit(1) } // 移除defer Conn.Close(),避免连接被提前关闭 }
同时在main.go中添加程序退出时的连接关闭逻辑:
func main() { // ... 其他初始化逻辑 db.InitDatabase(cfg) defer db.Conn.Close() // 程序退出时统一关闭连接 // ... 启动gin服务等逻辑 }
修复Task指针初始化问题(controller.go)
将response声明为值类型或提前初始化指针:
func GetTasks(c *gin.Context) { // 方案1:使用值类型(推荐) var response Task // SQL明确指定列名,避免表结构变更导致字段不匹配 err := db.Conn.QueryRow(context.Background(), "select title, description from tasks").Scan(&response.Title, &response.Description) // 方案2:初始化指针 // response := &Task{} // err := db.Conn.QueryRow(...).Scan(&response.Title, &response.Description) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return // 错误时终止后续逻辑 } c.JSON(http.StatusOK, gin.H{ "page": "gettasks", "tasks": response, }) }
内容的提问来源于stack exchange,提问作者fishkaoff
相关产品推荐
相关产品推荐

