goang switch语句中undefined报错处理
同事在研究Grafana reporter,一个通过把页把转化为pdf并可以邮件报告的工具。在其中引入的某个模块部分,其调用时发现报错。我对zabbix的东西久未关注了,帮其看了下报错,把报错的模块单独抽离出来单独调用发现其中报”undefined: rows”错误。代码逻辑比较简单,根据传入的id不同,执行不同的SQL并返回相应的值。具体代码如下:
1package main
2import (
3 _ "github.com/go-sql-driver/mysql"
4 "database/sql"
5 "fmt"
6)
7const (
8 mysql_user = "zabbix"
9 mysql_passwd = "361way.com"
10 mysql_ip = "10.211.139.10:3306" mysql_dbname = "zabbix"
11)
12func db(id int) int {
13 conn, err := sql.Open("mysql", mysql_user+":"+mysql_passwd+"@tcp("+mysql_ip+")/"+mysql_dbname)
14 if err != nil {
15 fmt.Println(err)
16 }
17 switch {
18 case id == 6:
19 rows,_ := conn.Query("select count(*) as num from daily_t1 where ((select max(runtimestamp) from daily_t1) - runtimestamp) <= 3")
20 case id == 8:
21 rows,_ := conn.Query("select count(*) as num from daily_t2 where ((select max(runtimestamp) from daily_t2) - runtimestamp) <= 3")
22 case id == 10:
23 rows,_ := conn.Query("select count(*) as num from daily_t3 where ((select max(runtimestamp) from daily_t3) - runtimestamp) <= 3")
24 }
25 defer rows.Close()
26 var num int
27 for rows.Next() {
28 err := rows.Scan(&num)
29 if err != nil {
30 panic(err)
31 }
32 }
33 if err != nil {
34 fmt.Println(err)
35 }
36 return num
37}
38func main() {
39 num := db(8)
40 fmt.Println(num)
41}
猛一看,代码确实未发现明显错误,冒号确实是已经做了变量定义了。因为这段代码如果去掉switch语句,单独只用一句,完全可以正常执行,换用switch和if都不行。处理思路也比较简单,逻辑外定义,逻辑内再赋值就好了,这里只列下主要更改的部分,如下:
1var num int
2var rows *sql.Rows
3switch {
4case id == 6:
5 row, _ := conn.Query("select count(*) as num from daily_t1 where ((select max(runtimestamp) from daily_t1) - runtimestamp) <= 3")
6 rows = row
7case id == 8:
8 row, _ := conn.Query("select count(*) as num from daily_t2 where ((select max(runtimestamp) from daily_t2) - runtimestamp) <= 3")
9 rows = row
10case id == 10:
11 row, _ := conn.Query("select count(*) as num from daily_t3 where ((select max(runtimestamp) from daily_t3) - runtimestamp) <= 3")
12 rows = row
13default:
14 num = 0
15}
16defer rows.Close()
但是这个感觉能用性不强啊,能不能换种看起来逻辑更通顺的搞法。可以单独对要处理的语句做一层封装,再在后面的逻辑处理里调用不就好了。如果返回的值不同,只要上面的封装部分中修改就行了。再次修改也能正常执行的代码如下:
1func DoQuery(db *sql.DB, sqlInfo string) int {
2 var num int
3 rows, err := db.Query(sqlInfo)
4 if err != nil {
5 log.Fatal(err)
6 num = 0
7 }
8 defer rows.Close()
9 for rows.Next() {
10 //var num int
11 if err := rows.Scan(&num); err != nil {
12 log.Fatal(err)
13 num = num
14 //return num,nil
15 }
16 }
17 return num
18}
19func db(id int) int {
20 conn, err := sql.Open("mysql", mysql_user+":"+mysql_passwd+"@tcp("+mysql_ip+")/"+mysql_dbname)
21 if err != nil {
22 fmt.Println(err)
23 }
24 row6 := "select count(*) as num from daily_t1 where ((select max(runtimestamp) from daily_t1) - runtimestamp) <= 3"
25 row8 := "select count(*) as num from daily_t2 where ((select max(runtimestamp) from daily_t2) - runtimestamp) <= 3"
26 row10 := "select count(*) as num from daily_t3 where ((select max(runtimestamp) from daily_t3) - runtimestamp) <= 3"
27 var num int
28 if id == 6 {
29 num = DoQuery(conn,row6)
30 }
31 if id == 8 {
32 num = DoQuery(conn,row8)
33 }
34 if id == 10 {
35 num = DoQuery(conn,row10)
36 }
37 return num
38}
当前的问题是解决了,因为这里调用的是count语句,明确返回是一个整型值。如果是select某个表的limit 10条数据呢?返回的是多值怎么办?可以通过ql Rows的执行结果转化保存成map,上面的封装代码就变成了如下:
1func DoQuery(db *sql.DB, sqlInfo string, args ...interface{}) ([]map[string]interface{}, error) {
2 rows, err := db.Query(sqlInfo, args...)
3 if err != nil {
4 return nil, err
5 }
6 columns, _ := rows.Columns()
7 columnLength := len(columns)
8 cache := make([]interface{}, columnLength) //临时存储每行数据
9 for index, _ := range cache { //为每一列初始化一个指针
10 var a interface{}
11 cache[index] = &a
12 }
13 var list []map[string]interface{} //返回的切片
14 for rows.Next() {
15 _ = rows.Scan(cache...)
16 item := make(map[string]interface{})
17 for i, data := range cache {
18 item[columns[i]] = *data.(*interface{}) //取实际类型
19 }
20 list = append(list, item)
21 }
22 _ = rows.Close()
23 return list, nil
24}
可以说上面这个的逻辑处理通用性更强了。
当然,其实也可以不用这么麻烦,使用gorm模块不就完事了。语句写的更短(不过没有直接SQL语句看起来直观,有利有弊吧),具体GORM的使用可以参看官方页面:http://gorm.io/zh_CN/docs/query.html
捐赠本站(Donate)
如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))
- Author: shisekong
- Link: https://blog.361way.com/golang-undefined/6286.html
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.