执行MySQL查询时返回空值

huangapple go评论85阅读模式
英文:

go mysql returning null values

问题

我目前正在处理一个使用Golang Google App Engine的项目,并遇到了一个小问题。我有一个名为"party"的数据库,其中包含一个名为"parties"的表。问题是,当执行以下代码时,会打印一个空的JSON数组 - 实际上它的长度是正确的,但它只包含空的Parties。(而且我的数据库中确实有条目)

以下是代码的一部分:

func getParties(w http.ResponseWriter, r *http.Request) {
    rows := getRowsFromSql("select * from parties;")
    parties := scanForParties(rows)

    json, _ := json.Marshal(parties)
    fmt.Fprint(w, string(json))
}

func scanForParties(rows *sql.Rows) []Party {
    var parties []Party

    for rows.Next() {
        var id int
        var name, author, datetime, datetime_to, host, location, description, longtitude, latitude, primary_image_id string
        rows.Scan(&id, &name, &author, &datetime, &datetime_to, &host, &location, &description, &longtitude, &latitude, &primary_image_id)
        party := Party{
            Id:           id,
            Name:         name,
            Author:       author,
            Datetime:     datetime,
            Datetime_to:  datetime_to,
            Host:         host,
            Location:     location,
            Description:  description,
            Longtitude:   longtitude,
            Latitude:     latitude,
            PrimaryImgId: primary_image_id,
        }
        parties = append(parties, party)
    }

    return parties
}

func getRowsFromSql(query string) *sql.Rows {
    con, err := sql.Open("mysql", dbConnectString)
    if err != nil {
        panic(err)
    }
    defer con.Close()

    rows, err2 := con.Query(query)
    if err != nil {
        panic(err2)
    }
    return rows

}

type Party struct {
    Id           int
    Name         string
    Author       string
    Datetime     string
    Datetime_to  string
    Host         string
    Location     string
    Description  string
    Longtitude   string
    Latitude     string
    PrimaryImgId string
}

这是我的parties表:

mysql> describe parties;
+------------------+----------------+------+-----+-------------------+-----------------------------+
| Field            | Type           | Null | Key | Default           | Extra                       |
+------------------+----------------+------+-----+-------------------+-----------------------------+
| id               | int(11)        | NO   | PRI | NULL              | auto_increment              |
| name             | varchar(64)    | NO   |     |                   |                             |
| author           | varchar(64)    | YES  |     | NULL              |                             |
| datetime         | datetime       | YES  |     | NULL              |                             |
| last_edited      | timestamp      | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| datetime_to      | datetime       | YES  |     | NULL              |                             |
| host             | text           | YES  |     | NULL              |                             |
| location         | text           | YES  |     | NULL              |                             |
| description      | text           | YES  |     | NULL              |                             |
| longitude        | decimal(23,20) | YES  |     | NULL              |                             |
| latitude         | decimal(23,20) | YES  |     | NULL              |                             |
| primary_image_id | varchar(256)   | YES  |     | NULL              |                             |
+------------------+----------------+------+-----+-------------------+-----------------------------+

然而,这个旧版本的代码完全正常:

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

    con, dbErr := sql.Open("mysql", dbConnectString)

    defer con.Close()

    if dbErr == nil {
        rows, _ := con.Query("select id, name, author, datetime from parties where datetime >= NOW();")

        var parties []Party

        var id int
        var name string
        var author string
        var datetime string

        for rows.Next() {
            rows.Scan(&id, &name, &author, &datetime)
            party := Party{}
            party.Id = id
            party.Name = name
            party.Author = author
            party.Datetime = datetime
            parties = append(parties, party)
        }

        if len(parties) > 0 {
            json, _ := json.Marshal(parties)
            fmt.Fprint(w, string(json))
        } else {
            fmt.Fprint(w, "{}")
        }

    } else {
        fmt.Fprint(w, "{\"Error\"}")
    }
}

有任何想法为什么会出现这种情况吗?提前谢谢 执行MySQL查询时返回空值

英文:

I am currently working on a Golang Google App Engine Project and have run into a small problem. I have a database "party" with table "parties". The problem is that when the following code is executed, a EMPTY json array is printed - it actually is properly long, but it only contains empty Parties. (And I do have entries in my database)

Go code (not all of it):

func getParties(w http.ResponseWriter, r *http.Request) {
rows := getRowsFromSql("select * from parties;")
parties := scanForParties(rows)
json, _ := json.Marshal(parties)
fmt.Fprint(w, string(json))
}
func scanForParties(rows *sql.Rows) []Party {
var parties []Party
for rows.Next() {
var id int
var name, author, datetime, datetime_to, host, location, description, longtitude, latitude, primary_image_id string
rows.Scan(&id, &name, &author, &datetime, &datetime_to, &host, &location, &description, &longtitude, &latitude, &primary_image_id)
party := Party{
Id:           id,
Name:         name,
Author:       author,
Datetime:     datetime,
Datetime_to:  datetime_to,
Host:         host,
Location:     location,
Description:  description,
Longtitude:   longtitude,
Latitude:     latitude,
PrimaryImgId: primary_image_id,
}
parties = append(parties, party)
}
return parties
}
func getRowsFromSql(query string) *sql.Rows {
con, err := sql.Open("mysql", dbConnectString)
if err != nil {
panic(err)
}
defer con.Close()
rows, err2 := con.Query(query)
if err != nil {
panic(err2)
}
return rows
}
type Party struct {
Id           int
Name         string
Author       string
Datetime     string
Datetime_to  string
Host         string
Location     string
Description  string
Longtitude   string
Latitude     string
PrimaryImgId string
}

And my parties table:

mysql> describe parties;
+------------------+----------------+------+-----+-------------------+-----------------------------+
| Field            | Type           | Null | Key | Default           | Extra                       |
+------------------+----------------+------+-----+-------------------+-----------------------------+
| id               | int(11)        | NO   | PRI | NULL              | auto_increment              |
| name             | varchar(64)    | NO   |     |                   |                             |
| author           | varchar(64)    | YES  |     | NULL              |                             |
| datetime         | datetime       | YES  |     | NULL              |                             |
| last_edited      | timestamp      | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| datetime_to      | datetime       | YES  |     | NULL              |                             |
| host             | text           | YES  |     | NULL              |                             |
| location         | text           | YES  |     | NULL              |                             |
| description      | text           | YES  |     | NULL              |                             |
| longitude        | decimal(23,20) | YES  |     | NULL              |                             |
| latitude         | decimal(23,20) | YES  |     | NULL              |                             |
| primary_image_id | varchar(256)   | YES  |     | NULL              |                             |
+------------------+----------------+------+-----+-------------------+-----------------------------+

However, this old version of code works just fine:

func getParties(w http.ResponseWriter, r *http.Request) {
con, dbErr := sql.Open("mysql", dbConnectString)
defer con.Close()
if dbErr == nil {
rows, _ := con.Query("select id, name, author, datetime from parties where datetime >= NOW();")
var parties []Party
var id int
var name string
var author string
var datetime string
for rows.Next() {
rows.Scan(&id, &name, &author, &datetime)
party := Party{}
party.Id = id
party.Name = name
party.Author = author
party.Datetime = datetime
parties = append(parties, party)
}
if len(parties) > 0 {
json, _ := json.Marshal(parties)
fmt.Fprint(w, string(json))
} else {
fmt.Fprint(w, "{}")
}
} else {
fmt.Fprint(w, "{\"Error\"}")
}
}

Any idea why this happens?
Thanks in advance 执行MySQL查询时返回空值

答案1

得分: 1

这只是一个猜测,但我认为问题出在你在这里关闭了与数据库的连接:

defer con.Close()

getRowsFromSql返回时,这将关闭与数据库的连接,所以当你在scanForParties中开始调用rows.Next()时,数据库连接已经关闭了。一旦数据库连接关闭,任何行的集合都将不再可用。

可能会因此返回一个error,但由于你没有在任何地方检查错误,所以你不会知道。在Go语言中,习惯上在函数可能返回错误时检查错误(其他语言也是如此,只是在Go语言中更加如此,因为没有异常机制)。

英文:

This is a guess, but I'm thinking that it's because you're closing the connection to the database here:

defer con.Close()

This will close the connection to the database when getRowsFromSql returns, so by the time you start calling rows.Next() in scanForParties the DB connection is gone. Once the DB connection is closed, any collection of rows will no longer be available.

Something is probably returning an error because of this, but since you're not checking any errors anywhere you won't know. In Go it is idiomatic to check for errors whenever a function can return one (and other languages too, just more so in Go because of the lack of exceptions).

答案2

得分: 1

好的,以下是翻译好的内容:

好的,其他人关于错误的说法都是正确的:rows.Scan() 返回一个错误。当我最终检查时,它说提供的扫描变量不足。简单修复:添加缺失的变量。

谢谢大家 执行MySQL查询时返回空值

英文:

Okay so all the others were right about the errors: rows.Scan() returns an error. And when I finally checked it, it said that there are insufficient scan variables provided. Simple fix: add the missing one.

Thank you guys 执行MySQL查询时返回空值

huangapple
  • 本文由 发表于 2015年4月2日 02:00:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/29397645.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定