duanlang1531 2015-03-10 13:30
浏览 54
已采纳

在GO中重用数据库连接和“无效的内存地址”错误

I'm new to GO, and can't seem to find any information on an error with reusing a database connection in a global. Here's a simplified version of my code that caues the error:

package main

import (
    _ "github.com/denisenkom/go-mssqldb"
    "database/sql"
)

var debug = flag.Bool("debug", false, "enable debugging")
var password = flag.String("password", "*****", "the database password")
var port *int = flag.Int("port", 1433, "the database port")
var server = flag.String("server", "localhost", "the database server")
var user = flag.String("user", "*****", "the database user")
var db *sql.DB

func main() {
    // Parse the incoming flags to set variables.
    flag.Parse()

    // Output the database variables if the debug flag is set.
    if *debug {
        fmt.Printf(" password:%s
", *password)
        fmt.Printf(" port:%d
", *port)
        fmt.Printf(" server:%s
", *server)
        fmt.Printf(" user:%s
", *user)
    }

    // Build out the connection string to the database, and then open the connection to the database.
    connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d", *server, *user, *password, *port)
    if *debug { fmt.Printf(" connString:%s
", connString) }
    db, err := sql.Open("mssql", connString)
    if err != nil { log.Fatal("Open connection failed:", err.Error()) }
    err = db.Ping()
    if err != nil {
        fmt.Println("Cannot connect: ", err.Error())
        return
    }

    // Close the connection when we're all done.
    defer db.Close()

    // Truncate the existing records in the ListHubFeed
    res, err := db.Exec( `
        TRUNCATE TABLE foo
    ` )
    _ = res

    if err != nil {
        fmt.Println( "TRUNCATE TABLE failed", err )
    }

    eligible := verifyEligibility( "foo" )

}

func verifyEligibility( email string ) ( success bool ) {

    //Run each check individually, and if any one fails, return false and stop processing additional checks

    // if the routing email is bad, then we can't create an account, so kick it out.
    if( !govalidator.IsEmail( email ) ){
        writeToLog( email )
        return false
    }

    return true;

}

func writeToLog( tolog string ) {
    res, err := db.Exec(`
        INSERT INTO Log ( 
            Email
        ) VALUES (
            ?,
            ?,
            ?,
            ?
        )` , tolog )
    if err != nil {
        fmt.Println( "insert failed", err )
    }
    _ = res
}

That's really ugly psuedocode, but the point is that the TRUNCATE statements in main run just fine, but after calling verifyEligibility() and then attempting to log the entry in the writeToLog() function, I get the following error:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pc=0x46d485]

goroutine 1 [running]:
database/sql.(*DB).conn(0x0, 0xc082044088, 0x0, 0x0)
        c:/go/src/database/sql/sql.go:634 +0x7b5
database/sql.(*DB).exec(0x0, 0x742730, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        c:/go/src/database/sql/sql.go:884 +0x9d
database/sql.(*DB).Exec(0x0, 0x742730, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        c:/go/src/database/sql/sql.go:875 +0xd4
main.writeToLog(0xc082004a20, 0x11, 0x70f370, 0x5, 0x0, 0x0, 0x777ef0, 0x24, 0x71ba70, 0x3)

I can't find any information on this error as it relates to go-mssqldb. db is declared as a global, and is opened in main, so I can't figure out why it's not available to me in writeToLog().

  • 写回答

1条回答 默认 最新

  • dse323222 2015-03-10 13:35
    关注

    Your problem is that the db pointer is nil in the context of your writeToLog() function. The culprit is this line:

    db, err := sql.Open("mssql", connString)
    

    Here, you are confusing the short variable declaration operator (:=) with the assignment operator (=).

    This instruction override the db global variable with a db local variable, only accessible in your main function (this is called shadowing, and also work with package names, etc). Consequently, the db variable used in writeToLog is never initialized, hence the nil pointer dereference error.

    To fix it, you just have to fix your declaration for it to be an affectation:

    var err error
    db, err = sql.Open("mssql", connString)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 路易威登官网 里边的参数逆向
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程
  • ¥20 模型在y分布之外的数据上预测能力不好如何解决
  • ¥15 processing提取音乐节奏
  • ¥15 gg加速器加速游戏时,提示不是x86架构
  • ¥15 python按要求编写程序
  • ¥15 Python输入字符串转化为列表排序具体见图,严格按照输入