我是golang的新手。我试图用golang对mysql数据库进行并发查询。我知道频道可以是类型界面。当我在tableData (type map)
函数中打印RunQuery
时,我得到了结果。我正在向tableData
发送ch
,即类型接口的频道。在函数getdataList
中,我在ch
中没有任何价值。我不明白我做错了什么。
以下是我的代码:
package main
import (
"database/sql"
"fmt"
"net/http"
_ "github.com/go-sql-driver/mysql"
"log"
)
var db *sql.DB
func getdataList(id int) {
ch := make(chan interface{})
done := make (chan bool)
RunQuery(ch,"select id,name, last_name,first_name from persons where id= ?", id)
go func() {
for {
x, ok := <-ch //I am not getting any data in channel here
if ok {
fmt.Println(x)
}else {
fmt.Println("done")
done <- true
return
}
}
}()
}
func RunQuery (ch chan interface{}, query string, param interface{}) {
stmt, err := db.Prepare(query)
if err != nil {
panic(err.Error())
}
defer stmt.Close()
rows, err := stmt.Query(param)
columns, err := rows.Columns()
if err != nil {
fmt.Println("Failed to get columns", err)
return
}
count := len(columns)
tableData := make([]map[string]interface{}, 0)
values := make([]interface{}, count)
valuePtrs := make([]interface{}, count)
for rows.Next() {
for i := 0; i < count; i++ {
valuePtrs[i] = &values[i]
}
rows.Scan(valuePtrs...)
entry := make(map[string]interface{})
for i, col := range columns {
var v interface{}
val := values[i]
b, ok := val.([]byte)
if ok {
v = string(b)
} else {
v = val
}
entry[col] = v
}
tableData = append(tableData, entry)
}
fmt.Pritln(tableData) //here I am getting data in map
ch <- tableData
}
func dbtest(w http.ResponseWriter, req *http.Request) {
go getdataList(2)
go getdataList(3)
}
func main() {
var err error
db, err = sql.Open("mysql", "root:@/dbName")
if err != nil {
panic(err.Error())
}
defer db.Close()
http.HandleFunc("/dbTest", dbtest)
log.Fatal(http.ListenAndServe(":8080", nil))
}
答案 0 :(得分:0)
您的代码存在的问题是,在从通道读取数据之前,它会阻止执行流程。当您从RunQuery
致电getdataList
时,RunQuery
会尝试通过频道ch
发送数据。但是,没有任何内容从ch
读取,因为从中读取的代码位于getdataList
,而且位于RunQuery
的调用之下。
因此,RunQuery
永远不会返回,并且从ch
读取的goroutine永远不会触发。要修复,您也可以尝试将RunQuery
作为goroutine运行:
func getdataList(id int) {
ch := make(chan interface{})
done := make (chan bool)
// run in a goroutine
go RunQuery(ch,"select id,name, last_name,first_name from persons where id= ?", id)
go func() {
for {
x, ok := <-ch //I am not getting any data in channel here
if ok {
fmt.Println(x)
}else {
fmt.Println("done")
done <- true
return
}
}
}()
}
您的代码中还有另一个问题。你永远不会关闭ch
。这可能会导致死锁。最理想的地方似乎是RunQuery
:
func RunQuery (ch chan interface{}, query string, param interface{}) {
// ...
ch <- tableData
close(ch)
}