golang - mysql 恐慌:运行时错误:无效的内存地址或 nil 指针取消引用

Posted

技术标签:

【中文标题】golang - mysql 恐慌:运行时错误:无效的内存地址或 nil 指针取消引用【英文标题】:golang - mysql panic: runtime error: invalid memory address or nil pointer dereference 【发布时间】:2022-01-05 05:30:34 【问题描述】:

我尝试使用 golang 建立一个简单的连接并从数据库中获取数据,这里是包含我的 API 试用版的程序:

package main

    

import (
    // "encoding/json"
    "log"
    "net/http"
    "fmt"
    // "math/rand"
    // "strconv"
    "github.com/gorilla/mux"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

// Book Struct(Model)
// type Book struct 
//  ID      string  `json:"id"`
//  Isbn    string  `json:"isbn"`
//  Title   string  `json:"title"`
//  // Author   *Author `json:"author"`
// 

// Article Struct(Model)
type Article struct 
    Author  string  `json:"author"`
    Title   string  `json:"title"`
    Body    string  `json:"body"`
    Created string  `json:"created"`


// //Author struct
// type Author struct 
//  Firstname   string  `json:"firstname"`
//  Lastname    string  `json:"lastname"`
// 

// Init books var as a slice book struct
// var books []Book

//get All Books
func getBooks(w http.ResponseWriter, r *http.Request) 
    w.Header().Set("Content-Type", "application/json")
    // json.NewEncoder(w).Encode(books)

//get single book
func getBook(w http.ResponseWriter, r *http.Request) 
    //

//create new book
func createBook(w http.ResponseWriter, r *http.Request) 
    //

//get All Books
func updateBook(w http.ResponseWriter, r *http.Request) 
    //

//get All Books
func deleteBook(w http.ResponseWriter, r *http.Request) 
    //


func main() 
    //init router
    r:= mux.NewRouter()

    //mock Data - @todo - implement DB
    // books = append(books, BookID: "1", Isbn: "436455", Title: "Book One", Author: &AuthorFirstname: "John", Lastname: "Doe")
    // books = append(books, BookID: "2", Isbn: "436444", Title: "Book two", Author: &AuthorFirstname: "Samuel", Lastname: "Etoo")


    db, err := sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/api_golang")
    if err != nil 
        panic(err.Error())
    

    defer db.Close()

    getarticle, err := db.Query("SELECT * FROM article")


    for getarticle.Next() 
        var article Article

        err = getarticle.Scan(&article.Author)
        if err != nil 
            panic(err.Error())
        
        fmt.Println(article.Author)
    
    //Route Handlers
    r.HandleFunc("/api/books", getBooks).Methods("GET")
    r.HandleFunc("/api/books/id", getBook).Methods("GET")
    r.HandleFunc("/api/books", createBook).Methods("POST")
    r.HandleFunc("/api/booksid", updateBook).Methods("PUT")
    r.HandleFunc("/api/booksid", deleteBook).Methods("DELETE")

    log.Fatal(http.ListenAndServe(":8000", r))



这是构建并在 docker 容器中运行程序后的错误报告:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x618087]

goroutine 1 [running]:
database/sql.(*Rows).Next(0x0)
    /usr/local/go/src/database/sql/sql.go:2944 +0x27
main.main()
    /app/app.go:83 +0x165

我已经确定程序在尝试连接 mysql 数据库时运行良好。

[更新] 对于数据库连接,我使用 xampp for linux,其中包含 apache 和 mysql。所以,数据库不是从 docker 安装的。

【问题讨论】:

getarticle, err := db.Query("SELECT * FROM article") 返回一个非零错误,你应该处理它。 我按照你的回答,得到另一个错误panic: dial tcp 127.0.0.1:3306: connect: connection refused。也请检查我的更新@mkopriva 你本地的mysql服务在运行吗?您可以不使用 Golang 而是在命令行中使用 mysql -h 127.0.0.1 -P 3306 -u root 连接它吗?或telnet 127.0.0.1 3306 也尝试阅读dev.mysql.com/doc/refman/8.0/en/can-not-connect-to-server.html 并遵循建议。 从官方repo看来mysql驱动有很多问题,我不能再检查了。 【参考方案1】:

1.用密码试试

db, err := sql.Open("mysql",
    "user:password@tcp(127.0.0.1:3306)/test")
if err != nil 
    log.Fatal(err)

defer db.Close() 

    结构体:文章有4个参数,所以使用“scan”时,“select * from ...”时也需要4个参数。

    “从文章中选择作者”

【讨论】:

感谢您的回答。但是这次我只是离开了 mysql,因为问题扩展到了许多不同的问题。所以然后我转向postgres。我还没有时间检查这个答案。

以上是关于golang - mysql 恐慌:运行时错误:无效的内存地址或 nil 指针取消引用的主要内容,如果未能解决你的问题,请参考以下文章

golang http 恐慌的全局恢复处理程序

如何使用不同的方法多次模拟调用 AWS 服务的 Golang 函数的单元测试?

golang golang恐慌

Golang恐慌崩溃预防

Golang 模拟上下文恐慌

在golang中输入正确但输出恐慌