Golang中解决HTTP服务运行时panic:无效内存地址或空指针引用问题
Golang中解决HTTP服务运行时panic:无效内存地址或空指针引用问题 errorlog.txt
出现以下错误:
2020/05/11 14:58:19 http: panic serving [::1]:51401: runtime error: invalid memory address or nil pointer dereference
goroutine 19 [running]:
net/http.(*conn).serve.func1(0xc00012adc0)
c:/go/src/net/http/server.go:1767 +0x140
panic(0x7330c0, 0xa20e50)
c:/go/src/runtime/panic.go:679 +0x1c0
sync.(*Mutex).Lock(...)
c:/go/src/sync/mutex.go:74
此文件已被截断。显示完整内容
package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
此文件已被截断。显示完整内容
更多关于Golang中解决HTTP服务运行时panic:无效内存地址或空指针引用问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你的 db 变量在不同函数中使用时为 nil,因为在这行代码中,你实际上声明了一个同名的局部变量,它遮蔽了全局变量:
db, err := sql.Open("postgres", psqlInfo)
更多关于Golang中解决HTTP服务运行时panic:无效内存地址或空指针引用问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这个panic发生在尝试对nil指针调用sync.Mutex.Lock()方法。从错误堆栈看,问题出现在sync.(*Mutex).Lock()调用时,说明某个结构体中的Mutex字段是nil。
查看提供的cust.go文件,可以看到Customer结构体定义:
type Customer struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
mu sync.Mutex
}
问题可能出现在以下几种情况:
- 未初始化的Customer指针:当通过
new(Customer)或&Customer{}创建指针但未正确初始化时 - 数据库查询返回nil:从数据库查询Customer时可能返回nil指针
检查代码中的数据库查询部分,特别是getCustomer函数:
func getCustomer(db *sql.DB, id string) (*Customer, error) {
row := db.QueryRow("SELECT id, name, email FROM customers WHERE id = $1", id)
customer := &Customer{}
err := row.Scan(&customer.ID, &customer.Name, &customer.Email)
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
return customer, nil
}
这里的问题是当查询不到记录时,函数返回nil, nil。然后在HTTP处理器中直接使用这个返回值:
func (h *CustomerHandler) GetCustomer(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
customer, err := getCustomer(h.db, id)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 这里customer可能是nil
customer.mu.Lock() // panic发生在这里
defer customer.mu.Unlock()
json.NewEncoder(w).Encode(customer)
}
解决方案是在访问Mutex之前检查customer是否为nil:
func (h *CustomerHandler) GetCustomer(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
customer, err := getCustomer(h.db, id)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if customer == nil {
http.Error(w, "Customer not found", http.StatusNotFound)
return
}
customer.mu.Lock()
defer customer.mu.Unlock()
json.NewEncoder(w).Encode(customer)
}
另外,也可以修改getCustomer函数,使其在查询不到记录时返回明确的错误:
func getCustomer(db *sql.DB, id string) (*Customer, error) {
row := db.QueryRow("SELECT id, name, email FROM customers WHERE id = $1", id)
customer := &Customer{}
err := row.Scan(&customer.ID, &customer.Name, &customer.Email)
if err != nil {
if err == sql.ErrNoRows {
return nil, fmt.Errorf("customer with id %s not found", id)
}
return nil, err
}
return customer, nil
}
这样HTTP处理器中就不需要单独检查nil,只需要处理错误即可。

