如何检查空数组(结构体数组)

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

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
}

huangapple
  • 本文由 发表于 2015年1月20日 06:32:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/28034652.html
匿名

发表评论

匿名网友

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

确定