为什么无法从处理程序访问我的数据库连接?

我有这样的代码:


package main


import (

    "database/sql"

    "flag"

    "fmt"

    "log"

    "net/http"

    "os"


    _ "github.com/go-sql-driver/mysql"

)


// Default constant for configuration

const DefaultHTTPAddr = ":8080"

const DefaultDSN = "root:root@tcp(127.0.0.1:3306)/librarian"


// Parameters

var (

    httpAddr string

    dsn      string

    db       *sql.DB

)


// init initializes this package.

func init() {

    flag.StringVar(&httpAddr, "addr", DefaultHTTPAddr, "Set the HTTP bind address")

    flag.StringVar(&dsn, "dsn", DefaultDSN, "Set the Data Source Name")

    flag.Usage = func() {

        fmt.Fprintf(os.Stderr, "Usage: %s [options]\n", os.Args[0])

        flag.PrintDefaults()

    }


}


type Book struct {

    id     int

    title  string

    author string

}


func main() {

    flag.Parse()


    var err error

    db, err := sql.Open("mysql", DefaultDSN)

    if err != nil {

        log.Fatal(err)

    }

    if err = db.Ping(); err != nil {

        log.Fatal(err)

    }


    // handler

    http.HandleFunc("/", homepage)

    http.HandleFunc("/books", booksIndex)


    log.Println("httpd started successfully")

    http.ListenAndServe(httpAddr, nil)

}


func booksIndex(w http.ResponseWriter, r *http.Request) {

    if r.Method != "GET" {

        http.Error(w, http.StatusText(405), 405)

        return

    }


    rows, err := db.Query("SELECT * FROM books")

    if err != nil {

        log.Fatal(err)

    }

    defer rows.Close()


    books := make([]*Book, 0)

    for rows.Next() {

        bk := new(Book)

        err = rows.Scan(&bk.id, &bk.title, &bk.author)

        if err != nil {

            log.Fatal(err)

        }

        books = append(books, bk)

    }

    if err = rows.Err(); err != nil {

        log.Fatal(err)

    }


    for _, bk := range books {

        fmt.Fprintf(w, "%v, %v, %v\n", bk.id, bk.title, bk.author)

    }

}


我以为我可以db在booksIndex设置为全局变量时访问。当我将数据库初始化移动到booksIndex错误时不会出现。


我的代码中有哪些部分有问题?


另外,我是 Golang 的新手。如果您对如何组织我的代码有任何建议,请告诉我。谢谢.. :)


叮当猫咪
浏览 137回答 1
1回答

慕村9548890

您在函数中的 db 变量正在遮蔽全局变量。当你这样做时:db,err:=它将它分配给一个新的局部变量 db。这是因为它不是来自同一个区块。根据标准:与常规变量声明不同,短变量声明可以重新声明变量,前提是它们最初是在同一个块(或参数列表,如果该块是函数体)中以相同类型声明的,并且至少有一个非空白变量是新的。因此,重新声明只能出现在多变量短声明中。重新声明不引入新变量;它只是为原始值分配一个新值。所以全局变量仍然是 nil 指针。当它被访问时,你会得到 nil 指针解引用将其更改为 d,然后稍后将其分配给 db。或者哪个更正确(如rahmat的评论中给出的):=d , err =我建议您为处理程序、模型等设置单独的文件。并查看https://github.com/mattermost/platform以了解如何组织代码。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go