go mysql returning null values

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 :)

Upvotes: 0

Views: 2556

Answers (2)

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 :)

Upvotes: 1

robbrit
robbrit

Reputation: 17960

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).

Upvotes: 1

Related Questions