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 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看