Mysql: * عنوان ذاكرة غير صالح لـ sql.DB أو عدم وجود مرجع للمؤشر

تم إنشاؤها على ٢ نوفمبر ٢٠١٣  ·  21تعليقات  ·  مصدر: go-sql-driver/mysql

// الملف /Users/jinke/golang/src/cds_spider/common/dbpool/mysql.go

package dbpool

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

var DB *sql.DB

func init() {
    db, err := sql.Open("mysql", "root:123456@tcp(192.168.1.20:3306)/?charset=utf8")
    if err != nil {
        panic("dbpool init >> " + err.Error())
    }
    DB = db
    DB.SetMaxIdleConns(5)
}

// الملف / المستخدمون/jinke/golang/src/cds_spider/newCar/koubei/koubei.go

package koubei

import (
    "cds_spider/common/dbpool"
)

type KouBei struct {
    Auto_koubei_id                                               int
    Source                                                       string
    Auto_brand_id, Auto_company_id, Auto_serial_id, Auto_type_id int
    Username                                                     string
    Price                                                        float64
    Province_id, City_id                                         int
    Buy_date, Content, Spider_url, Created                       string
    Level                                                        int
}

func (k *KouBei) Save() (insertID int64, err error) {
    stmt, err := dbpool.DB.Prepare("INSERT mains.koubei SET source=?, auto_brand_id=?, auto_company_id=?, auto_serial_id=?, auto_type_id=?, username=?, price=?, province_id=?, city_id=?, buy_date=?, content=?, level=?, spider_url=?")
    if err != nil {
        return 0, err
    }
    defer stmt.Close()

    res, err := stmt.Exec(k.Source, k.Auto_brand_id, k.Auto_company_id, k.Auto_serial_id, k.Auto_type_id, k.Username, k.Price, k.Province_id, k.City_id, k.Buy_date, k.Content, k.Level, k.Spider_url)
    if err != nil {
        return 0, err
    }
    return res.LastInsertId()
}

"stmt، err: = dbpool.DB.Prepare" هو خطأ في عنوان ذاكرة غير صالح أو عدم وجود إشارة مرجعية للمؤشر

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x41 pc=0x52fb5c]

goroutine 2208 [running]:
github.com/go-sql-driver/mysql.(*mysqlConn).writeCommandPacketUint32(0x0, 0x1048eca19, 0xc2046b8330, 0x2ba32ae35a88)
    /Users/jinke/golang/src/github.com/go-sql-driver/mysql/packets.go:327 +0x1c
github.com/go-sql-driver/mysql.(*mysqlStmt).Close(0xc200e3ba50, 0x0, 0x0)
    /Users/jinke/golang/src/github.com/go-sql-driver/mysql/statement.go:24 +0x46
database/sql.(*driverConn).finalClose(0xc2020d5cc0, 0xc20370d900, 0x2bbc7f0)
    /usr/local/go/src/pkg/database/sql/sql.go:285 +0x87
database/sql.func·002(0xc2000ca200, 0xc2000aebd0)
    /usr/local/go/src/pkg/database/sql/sql.go:372 +0x2c
database/sql.(*driverConn).Close(0xc2020d5cc0, 0x3, 0x4a173d)
    /usr/local/go/src/pkg/database/sql/sql.go:278 +0x174
database/sql.(*DB).putConn(0xc2000ca1e0, 0xc2020d5cc0, 0x0, 0x0)
    /usr/local/go/src/pkg/database/sql/sql.go:598 +0x2e2
database/sql.(*DB).prepare(0xc2000ca1e0, 0x742450, 0xd2, 0xc20035ba50, 0x85, ...)
    /usr/local/go/src/pkg/database/sql/sql.go:640 +0x267
database/sql.(*DB).Prepare(0xc2000ca1e0, 0x742450, 0xd2, 0x4b2488, 0xc2000ae140, ...)
    /usr/local/go/src/pkg/database/sql/sql.go:608 +0x5a
cds_spider/newCar/koubei.(*KouBei).Save(0xc2046ab790, 0x0, 0x0, 0x0)
    /Users/jinke/golang/src/cds_spider/newCar/koubei/koubei.go:20 +0x6b
bug

التعليق الأكثر فائدة

methane ، لقد كنت على حق ، اضطررت إلى تغيير db, err := [...] بـ db, err = [...] إعلان الخطأ أيضًا. خطئي السيئ في تشتيت الانتباه.

ال 21 كومينتر

نحتاج إلى المعلومات التالية:

  • إصدار Go-MySQL-Driver الخاص بك (أو git SHA)
  • إصدار Go الخاص بك (قم بتشغيل go version في وحدة التحكم الخاصة بك)

انتقل الإصدار go1.1.2 darwin / amd64
Go-MySQL-Driver هو أحدث إصدار

أعتقد أن الذعر لا ينبغي أن يحدث مع v1.0.3 ، وهو إصدار bugfix أصدرناه أمس ( go get -able منذ بضع دقائق).

لكنني أتحرى أكثر ، تبدو أداة المكدس غريبة حقًا بالنسبة لي. سبب الذعر هو اتصال nil في stmt.Close (متغير mc ) حيث يجب ألا يكون الاتصال أبدًا nil مع الكود أعلاه.

يمكن للإصدار 1.0.3 أن يمنع على الأقل ذعر مؤشر عدم وجود مؤشر ، لأنه يتحقق من mc == nil أولاً

هل يمكنك إعادة إنتاج هذا الخطأ؟

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x41 pc=0x5304bc]
goroutine 25466 [running]:
github.com/go-sql-driver/mysql.(*mysqlConn).writeCommandPacketUint32(0x0, 0x305e92619, 0xc22b2fe650, 0x2b8b3c6167c0)
    /Users/jinke/golang/src/github.com/go-sql-driver/mysql/packets.go:327 +0x1c
github.com/go-sql-driver/mysql.(*mysqlStmt).Close(0xc22b87a6f0, 0x0, 0x0)
    /Users/jinke/golang/src/github.com/go-sql-driver/mysql/statement.go:24 +0x46
database/sql.(*driverConn).finalClose(0xc202a42780, 0xc2014fd1c0, 0x2210b5a80)
    /usr/local/go/src/pkg/database/sql/sql.go:Jump {0 autohome 25 44 258 1977 hkyjh 12.68 394 397 2011-9-27  http://k.autohome.com.cn/spec/8288/hkyjh 2013-11-02 14:21:38 6}
285 +0x87
database/sql.func·002(0xc2000ca200, 0xc2000aebd0)
    /usr/local/go/src/pkg/database/sql/sql.go:372 +0x2c
database/sql.(*driverConn).Close(0xc202a42780, 0x32, 0x9)
    /usr/local/go/src/pkg/database/sql/sql.go:278 +0x174
database/sql.(*DB).putConn(0xc2000ca1e0, 0xc202a42780, 0x0, 0x0)
    /usr/local/go/src/pkg/database/sql/sql.go:598 +0x2e2
database/sql.func·004()
    /usr/local/go/src/pkg/database/sql/sql.go:664 +0x41
database/sql.(*DB).exec(0xc2000ca1e0, 0x738330, 0x40, 0x2b8b3c616cb8, 0x2, ...)
    /usr/local/go/src/pkg/database/sql/sql.go:661 +0xb2
database/sql.(*DB).Exec(0xc2000ca1e0, 0x738330, 0x40, 0x2b8b3c616cb8, 0x2, ...)
    /usr/local/go/src/pkg/database/sql/sql.go:650 +0x98
cds_spider/newCar/koubei.AddOk(0x6dee10, 0x8, 0x1, 0x0, 0x0, ...)
    /Users/jinke/golang/src/cds_spider/newCar/koubei/log.go:49 +0x568
cds_spider/newCar/koubei.(*KouBei).Save(0xc20a0a74d0, 0x0, 0x0, 0x0)
    /Users/jinke/golang/src/cds_spider/newCar/koubei/koubei.go:29 +0x3b7
main.func·006()
    /Users/jinke/golang/src/cds_spider/newCar/koubei/main/autohome.go:241 +0x37
created by main.func·007

/Users/jinke/golang/src/cds_spider/newCar/koubei/log.go

func AddOk(source string, count int) error {
    row := dbpool.DB.QueryRow("SELECT * FROM cheduoshao_spider_status.koubei WHERE source=? AND spider_date=?", source, gcode.Date())
    var (
        id, quantity         int
        sources, spider_date string
    )

    row.Scan(&id, &sources, &quantity, &spider_date)

    if id == 0 {
        stmt, err := dbpool.DB.Prepare("INSERT cheduoshao_spider_status.koubei SET source=?, quantity=?, spider_date=?")
        if err != nil {
            return err
        }
        defer stmt.Close()

        _, err = stmt.Exec(source, 1, gcode.Date())
        if err != nil {
            return err
        }
    } else { 
        dbpool.DB.Exec("UPDATE main.koubei SET quantity=? WHERE id=?", quantity+1, id)
    }

    return nil
}

dbpool.DB.Exec ("UPDATE main.koubei SET quantity =؟ Where id =؟"، الكمية + 1، id) خطأ

يبدو أنه لم يعثر على مثل هذا الموقف من قبل ، فإن نظامي هو OS X 10.9

تحقق مما إذا كان row.Scan(&id, &sources, &quantity, &spider_date) يعرض خطأ.
هل جربت v1.0.3؟ كما قلت ، يجب على الأقل تجنب الذعر.

حاولت عدة مرات أكثر ، لقد قمت فقط بحذف الإصدار القديم ، ثم أعد المحاولة
لقد غيرت إلى:

err := row.Scan(&id, &sources, &quantity, &spider_date)
    if err != nil {
        return err
    }

أعتقد أنني تمكنت من إعادة إنتاج هذا الخطأ. مرة أخرى ، يرتبط هذا الخطأ بـ https://codereview.appspot.com/14920046 / Go الإصدار 5718 (أو # 98 ، # 142).
stmt.Exec يتجاهل أخطاء السائق ويعيد الاتصالات السيئة إلى التجمع.

يتضمن الإصدار 1.0.3 رقم 143 ، والذي على الأقل يتجنب حالات الذعر. الإصدار 1.1 ، الذي سيصدر في غضون ساعات قليلة ، سيتضمن # 151 ، مما يحسن هذا أكثر قليلاً.

أقترح إما تصحيح إصدار Go يدويًا باستخدام https://codereview.appspot.com/14920046 أو تجنب stmt.Exec حتى يتم إصدار الإصدار الثابت التالي مع هذا الإصلاح المضمّن. من المحتمل أن يكون هذا هو Go 1.3 في يونيو 2014 ...

وملاحظة إلى الكود الخاص بك أعلاه:
إذا كنت تستخدم stmt مرة واحدة فقط ، فلا داعي لتحضيرها يدويًا. فقط استخدم db.Exec ، وهو بالمناسبة لا يتم التنصت عليه مثل stmt.Exec .

إليك كيفية تعديل الكود الخاص بك أعلاه:

func AddOk(source string, count int) error {
    var (
        id, quantity         int
        sources, spider_date string
    )
    if err := dbpool.DB.QueryRow("SELECT * FROM cheduoshao_spider_status.koubei WHERE source=? AND spider_date=?", source, gcode.Date()).Scan(&id, &sources, &quantity, &spider_date); err != nil {
        return err
    }

    if id == 0 {
        if _, err =: dbpool.DB.Exec("INSERT cheduoshao_spider_status.koubei SET source=?, quantity=?, spider_date=?", source, 1, gcode.Date()); err != nil {
            return err
        }
    } else { 
        if _, err =: dbpool.DB.Exec("UPDATE main.koubei SET quantity=? WHERE id=?", quantity+1, id); err != nil {
            return err
        }
    }

    return nil
}

حسنا، شكرا!

أواجه هذه المشكلة أيضًا ، الإصدار go هو go1.7.4 linux/amd64 و go-sql-driver هو الأحدث. أنا أقوم بالاتصال بمثيل RDS من AWS.

runtime error: invalid memory address or nil pointer dereference
/usr/local/go/src/runtime/panic.go:458 (0x42c653)
    gopanic: reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
/usr/local/go/src/runtime/panic.go:62 (0x42b1ad)
    panicmem: panic(memoryError)
/usr/local/go/src/runtime/sigpanic_unix.go:24 (0x441054)
    sigpanic: panicmem()
/usr/local/go/src/database/sql/sql.go:781 (0x557d0a)
    (*DB).conn: db.mu.Lock()
/usr/local/go/src/database/sql/sql.go:1074 (0x559fbb)
    (*DB).query: ci, err := db.conn(strategy)
/usr/local/go/src/database/sql/sql.go:1062 (0x559dc0)
    (*DB).Query: rows, err = db.query(query, args, cachedOrNewConn)
/home/danilo/Go/src/github.com/DaniloMeritocracy/autocomplete/autocomplete.go:192 (0x402e27)
    _getJSON: rows, err := db.Query(sqlString)
/home/danilo/Go/src/github.com/DaniloMeritocracy/autocomplete/autocomplete.go:130 (0x402b54)
    school: res, err := _getJSON("SELECT * FROM university WHERE LOWER(name) LIKE '" + strings.Replace(term, "'", "\\'", -1) + "%' LIMIT 15")
/home/danilo/Go/src/github.com/DaniloMeritocracy/autocomplete/autocomplete.go:56 (0x403985)
    main.func1: results = school(term)
/home/danilo/Go/src/gopkg.in/gin-gonic/gin.v1/context.go:97 (0x45d53a)
    (*Context).Next: c.handlers[c.index](c)
/home/danilo/Go/src/gopkg.in/gin-gonic/gin.v1/recovery.go:45 (0x46d31a)
    RecoveryWithWriter.func1: c.Next()
/home/danilo/Go/src/gopkg.in/gin-gonic/gin.v1/context.go:97 (0x45d53a)
    (*Context).Next: c.handlers[c.index](c)
/home/danilo/Go/src/gopkg.in/gin-gonic/gin.v1/logger.go:72 (0x46c40f)
    LoggerWithWriter.func1: c.Next()
/home/danilo/Go/src/gopkg.in/gin-gonic/gin.v1/context.go:97 (0x45d53a)
    (*Context).Next: c.handlers[c.index](c)
/home/danilo/Go/src/gopkg.in/gin-gonic/gin.v1/gin.go:284 (0x4638ce)
    (*Engine).handleHTTPRequest: context.Next()
/home/danilo/Go/src/gopkg.in/gin-gonic/gin.v1/gin.go:265 (0x4631b0)
    (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/local/go/src/net/http/server.go:2202 (0x4e1fdd)
    serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/local/go/src/net/http/server.go:1579 (0x4de947)
    (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/local/go/src/runtime/asm_amd64.s:2086 (0x45c0f1)
    goexit: BYTE    $0x90   // NOP

هذه هي الدالة _getJSON ، التي تُرجع سلسلة النتائج

func _getJSON(sqlString string) (string, error) {
    rows, err := db.Query(sqlString)
    if err != nil {
        return "", err
    }
    defer rows.Close()
    columns, err := rows.Columns()
    if err != nil {
        return "", err
    }
    count := len(columns)
    tableData := make([]map[string]interface{}, 0)
    values := make([]interface{}, count)
    valuePtrs := make([]interface{}, count)
    for rows.Next() {
        for i := 0; i < count; i++ {
            valuePtrs[i] = &values[i]
        }
        rows.Scan(valuePtrs...)
        entry := make(map[string]interface{})
        for i, col := range columns {
            var v interface{}
            val := values[i]
            b, ok := val.([]byte)
            if ok {
                v = string(b)
            } else {
                v = val
            }
            entry[col] = v
        }
        tableData = append(tableData, entry)
    }
    jsonData, err := json.Marshal(tableData)
    if err != nil {
        return "", err
    }
    //fmt.Println(string(jsonData))
    return string(jsonData), nil
}

DaniloPolani ديسيبل الخاص بك هو لا شيء.

لماذا يجب أن يكون لا شيء؟ لدي db var خارج الوظائف var db *sql.DB وفي الوظيفة الرئيسية فتحت الاتصال مع

db, err := sql.Open("mysql", "<USERNAME>:<PASSWORD>@tcp(<HOST>:3306)/<DB_NAME>")
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()

ثم يتم استدعاؤها في _getJSON() . أوراق الاعتماد على ما يرام. ربما تكون مشكلة AWS؟ سأحاول مع المضيف المحلي.

db, err := sql.Open("mysql", "<USERNAME>:<PASSWORD>@tcp(<HOST>:3306)/<DB_NAME>")

إذن ، db هو المتغير المحلي الرئيسي ، وليس المتغير العام _getJSON() باستخدامه.

بدون تقديم رمز كامل قابل لإعادة الإنتاج ، لا يمكن لأحد الإشارة إليه
حيث كودك به حالة السباق.
go build -race صديقك.

methane ، لقد كنت على حق ، اضطررت إلى تغيير db, err := [...] بـ db, err = [...] إعلان الخطأ أيضًا. خطئي السيئ في تشتيت الانتباه.

فقط واجهت نفس المشكلة. مندهش أن هذا كان مشكلة.
الحل من خلال أعمال danilopolani @ .

danilopolanimethane أنقذوا وقتي يا رفاق

danilopolani أنت على حق ، شكرًا جزيلاً لك على مساعدتك ، لقد كنت أبحث عن هذه المشكلة لفترة طويلة ، شكرًا لك

تواجه نفس المشكلة .. كيف يمكنني استخدام حل

شكراً لميثان @ danilopolani لقد ارتكبت نفس الخطأ ، لحسن الحظ وجدت هذه المناقشة.

OMG ، لم أكن أتخيل أبدًا أن الحل كان يتعلق بتحديد نطاق المتغيرات.
شكرا جزيلا يا رفاق.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات