go - 运行时错误 : invalid memory address or nil pointer dereference (2)

标签 go

<分区>

我是 Go 的新手,需要帮助!

在 PostgreSQL 数据库中,我有一个名为 factors 的表。该表有 2 列(factor_idfactor_name)。现在,我已从 Go 应用程序成功连接到 PostgreSQL 数据库。

当我试图在控制台中发出基于查询的 GET 请求时,我看到了错误。

http://localhost:8000/api/factors/?limit=5&offset=1

我哪里弄错了?请帮助我解决问题。

controllers/factors.go:

package controllers

import (
    "encoding/json"
    "fmt"
    "net/http"
    "restify/models"
    "restify/utils"
)

var GetFactors = func(res http.ResponseWriter, req *http.Request) {
    data := models.Factors{}

    err := models.GetFactors(&data, req.URL.Query().Get("limit"), req.URL.Query().Get("offset"))
    if err != nil {
        fmt.Println(err.Error())
        http.Error(res, err.Error(), 500)
        return
    }

    out, err := json.Marshal(data)
    if err != nil {
        fmt.Println(err.Error())
        http.Error(res, err.Error(), 501)
        return
    }

    resp := make(map[string]interface{})

    resp["Dictionaries"] = string(out)

    utils.Respond(res, resp)

}

models/factors.go:

package models

import (
    "fmt"
    "restify/database"
)

type Factor struct {
    FactorID int `json:"factor_id"`
    FactorName string `json:"factor_name"`
}

type Factors struct {
    Array[]Factor
}

func GetFactors(data *Factors, limit string, offset string) error {
    rows, err := database.DB.Query(`SELECT * FROM factors ORDER BY factor_id LIMIT ` + limit + ` OFFSET ` + offset + `;`)
    if err != nil {
        fmt.Println(err)
        return err
    }
    defer rows.Close()
    for rows.Next() {
        var id int
        var name string
        model := Factor{}
        err = rows.Scan(&id, &name)
        if err != nil {
            fmt.Println(err)
            return err
        }
        model.FactorID = id
        model.FactorName = name
        data.Array = append(data.Array, model)
    }
    err = rows.Err()
    if err != nil {
        return err
    }
    return nil
}

错误:

2019/02/26 16:25:55 http: panic serving [::1]:20932: runtime error: invalid memory address or nil pointer dereference
goroutine 11 [running]:
net/http.(*conn).serve.func1(0xc0002badc0)
    C:/Go/src/net/http/server.go:1746 +0xd7
panic(0x6dad20, 0x970890)
    C:/Go/src/runtime/panic.go:513 +0x1c7
database/sql.(*DB).conn(0x0, 0x78a500, 0xc0000100a8, 0x10000c000339801, 0x0, 0xc000339898, 0xc000339830)
    C:/Go/src/database/sql/sql.go:1081 +0x41
database/sql.(*DB).query(0x0, 0x78a500, 0xc0000100a8, 0xc000356040, 0x3a, 0x0, 0x0, 0x0, 0xc000356001, 0x3a, ...)
    C:/Go/src/database/sql/sql.go:1514 +0x6d
database/sql.(*DB).QueryContext(0x0, 0x78a500, 0xc0000100a8, 0xc000356040, 0x3a, 0x0, 0x0, 0x0, 0x5, 0xc000356040, ...)
    C:/Go/src/database/sql/sql.go:1496 +0xda
database/sql.(*DB).Query(0x0, 0xc000356040, 0x3a, 0x0, 0x0, 0x0, 0x8, 0xc00034e016, 0x1)
    C:/Go/src/database/sql/sql.go:1510 +0x89
restify/models.GetFactors(0xc000339b28, 0xc00034e016, 0x1, 0xc00034e01e, 0x1, 0x0, 0x0)
    C:/Users/NNogerbek/go/src/restify/models/factors.go:18 +0xf6
restify/controllers.glob..func1(0x78a2c0, 0xc00035a000, 0xc000332200)
    C:/Users/NNogerbek/go/src/restify/controllers/factors.go:14 +0xd3
net/http.HandlerFunc.ServeHTTP(0x74da58, 0x78a2c0, 0xc00035a000, 0xc000332200)
    C:/Go/src/net/http/server.go:1964 +0x4b
github.com/gorilla/mux.(*Router).ServeHTTP(0xc0002fc180, 0x78a2c0, 0xc00035a000, 0xc000310300)
    C:/Users/NNogerbek/go/src/github.com/gorilla/mux/mux.go:212 +0xd7
github.com/gorilla/handlers.(*cors).ServeHTTP(0xc0001f2120, 0x78a2c0, 0xc00035a000, 0xc000310300)
    C:/Users/NNogerbek/go/src/github.com/gorilla/handlers/cors.go:54 +0xa95
net/http.serverHandler.ServeHTTP(0xc000056b60, 0x78a2c0, 0xc00035a000, 0xc000310300)
    C:/Go/src/net/http/server.go:2741 +0xb2
net/http.(*conn).serve(0xc0002badc0, 0x78a4c0, 0xc000340040)
    C:/Go/src/net/http/server.go:1847 +0x64d
created by net/http.(*Server).Serve
    C:/Go/src/net/http/server.go:2851 +0x2fc

database/database.go:

package database

import (
    "database/sql"
    "fmt"
    "github.com/joho/godotenv"
    _ "github.com/lib/pq"
    "log"
    "restify/utils"
)

var DB *sql.DB

/*
Function: "Connect".

Description:
The main task of the function is to initialize database connection.
*/
func Open() () {
    // Load environment variables from ".env" file.
    err := godotenv.Load(".env")
    if err != nil {
        panic(err)
    }

    // Initialize database related variables.
    dbUser := utils.CheckEnvironmentVariable("PostgreSQL_USER")
    dbPassword := utils.CheckEnvironmentVariable("PostgreSQL_PASSWORD")
    dbHost := utils.CheckEnvironmentVariable("PostgreSQL_HOST")
    dbName := utils.CheckEnvironmentVariable("PostgreSQL_DATABASE_NAME")

    // Defining connection string for PostgreSQL database.
    dbURL := fmt.Sprintf("user=%s password=%s host=%s dbname=%s sslmode=disable", dbUser, dbPassword, dbHost, dbName)

    // Create PostgreSQL database connection pool.
    DB, err := sql.Open("postgres", dbURL)
    if err != nil {
        panic(err)
    }

    // Ping PostgreSQL database to make sure it's alive.
    err = DB.Ping()
    if err != nil {
        panic(err)
    }

    log.Println("REST API web service successfully connected to remote PostgreSQL database.")
}

/*
Function: "Disconnect"

Description:
The main task of the function is to disconnect database connection.
*/
func Close() error {
    return DB.Close()
}

最佳答案

似乎问题是在此处分配 DB 时:

DB, err := sql.Open("postgres", dbURL) 

数据库在新范围内定义,因此这会创建一个局部变量而不是设置 pkg 级变量。 因此,代码 Open() 建立了到 DB 的连接。

试试这个:

var err error
DB, err = sql.Open("postgres", dbURL) 

这是官方引述:

Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.

关于go - 运行时错误 : invalid memory address or nil pointer dereference (2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54883657/

相关文章:

google-app-engine - GAE 上的 Paypal IPN 和 Golang 集成

sql - gorp: "auto_increment"附近:语法错误

由 reflect.New() 制作的 slice 的 JSON 编码在 golang 中给出 null

go - 无法无限期地写入一个 goroutine 并从另一个 goroutine 中读取

go - 在 goroutine 中更新全局变量的不同行为

mongodb - 从 channel 读取 SIGSEGV : segmentation violation

docker - docker 源中的 untaggedImage 和 deletedImage 有什么区别?

go - 在goLang中使用julienschmidt/httprouter时如何使用中间件?

mongodb - 从 Go 连接到远程 Linux MongoDb(无身份验证)

c - 尝试在 Go 中使用 C 包装器?