英文:
How to check for empty array (array of struct)
问题
一个mySQL查询函数返回一个被定义为
type Row []interface{}
的行数组。我想检查返回的数组是否为空,但是我得到了一个运行时错误:
s := fmt.Sprintf("select id, secret, shortname from beehives where shortname = '%s'", beehive)
rows, res, err := database.Query(s)
if err == nil {
if len(rows) != 1 {
如果rows为空,表达式len(rows)似乎会引发运行时错误。
我该如何检查一个空数组?我也尝试了rows == nil,但也会引发错误。
英文:
A mySQL Query function returns an array of rows witch is defined as
type Row []interface{}
I would like to check if the returned array is empty, but I get a runtime panic:
s := fmt.Sprintf("select id, secret, shortname from beehives where shortname = '%s'", beehive)
rows, res, err := database.Query(s)
if err == nil {
if len(rows) != 1 {
The expression len(rows) seems to cause the runtime panic if rows is empty.
How can I check for an empty array? I tried also rows == nil, which also panics.
答案1
得分: 7
看起来你可以使用QueryRow
,因为该查询预期只返回一行。
QueryRow执行一个预期最多返回一行的查询。QueryRow总是返回一个非nil值。错误会被推迟到调用Row的Scan方法时。
在这种情况下,如果没有行,会出现ErrNoRows
,但是直到出现.Scan
时才会推迟错误。
当QueryRow不返回行时,Scan会返回ErrNoRows。在这种情况下,QueryRow返回一个占位符*Row值,该值将此错误推迟到Scan时。
所以你想要做的是类似这样的:
var id int
var secret string
var shortname string
err := db.QueryRow("SELECT ...").Scan(&id, &secret, &shortname)
switch {
case err == sql.ErrNoRows:
log.Printf("Not found.")
case err != nil:
log.Fatal(err)
default:
//处理逻辑
}
另外,由于你需要循环遍历rows.Next
,你可以轻松设置一个标志:
defer rows.Close()
has_results := false
for rows.Next() {
has_results = true
//处理逻辑
}
if (!has_results) {
//错误处理
}
英文:
It looks like you could use QueryRow
, since that query is expected to return only one row.
> QueryRow executes a query that is expected to return at most one row. QueryRow always return a non-nil value. Errors are deferred until Row's Scan method is called.
In this case, if there is no row, the ErrNoRows
occurs, but is deferred until a .Scan
occurs.
> ErrNoRows is returned by Scan when QueryRow doesn't return a row. In such a case, QueryRow returns a placeholder *Row value that defers this error until a Scan.
So what you want to do is something like:
var id int
var secret string
var shortname string
err := db.QueryRow("SELECT ...").Scan(&id, &secret, &shortname)
switch {
case err == sql.ErrNoRows:
log.Printf("Not found.")
case err != nil:
log.Fatal(err)
default:
//do stuff
}
Otherwise, since you need to be looping over rows.Next
anyways, you can easily set a flag:
defer rows.Close()
has_results := false
for rows.Next() {
has_results = true
//do stuff
}
if (!has_results) {
//error handling
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论