When cross-compiling my code from Win10 to Linux, the following code stopped using rows.next
executed rows.Next()
rows, err := DB.Query("SELECT * FROM `machines`")
erh.Check(err)
newUsers := make(map[string]User, count)
defer erh.Check(rows.Close())
for rows.Next() {
//tu is temp user
tu := User{}
err := rows.Scan(&tu.Id, &tu.Name, &tu.Apikey, &tu.Ip, &tu.Machine, &tu.State, &tu.DbAvailable)
erh.Check(err)
log.Println(tu)
newUsers[tu.Apikey] = tu
}
When I placed the defer under rows.Next the rows.next code was executed
rows, err := DB.Query("SELECT * FROM `machines`")
erh.Check(err)
newUsers := make(map[string]User, count)
for rows.Next() {
//tu is temp user
tu := User{}
err := rows.Scan(&tu.Id, &tu.Name, &tu.Apikey, &tu.Ip, &tu.Machine, &tu.State, &tu.DbAvailable)
erh.Check(err)
log.Println(tu)
newUsers[tu.Apikey] = tu
}
defer erh.Check(rows.Close())
Can someone confirm this is a bug, or am I missing something here?
I'm not sure how this could work on Linux, it shouldn't. This line:
defer erh.Check(rows.Close())
Will execute rows.Close()
immediately, hold the return value, then defer only the call to erh.Check
. That's how defer works - arguments are evaluated immediately. From the docs:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.
If you want to use a construct like this, it would have to be within a closure, something like:
defer func() {
erh.Check(rows.Close())
}()
So that there are no arguments to evaluate at the time of defer
.