在Golang中,使用MySQL时,接口类型的通道未接收到值。

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

channel of type interface not receiving value in golang with MySql

问题

我是你的中文翻译助手,以下是你提供的代码的翻译:

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 // 在这里我没有收到任何数据
			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.Println(tableData) // 在这里我收到了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))

}

请注意,我只翻译了你提供的代码部分,其他内容不包括在内。如果你有任何问题,请随时提问。

英文:

I am new to golang. I am trying to do concurrent queries to mysql db with golang. I know channels can be of the type interface. When I print tableData (type map) in RunQuery function I am getting the result. I am sending tableData to ch i.e. channel of type interface. In function getdataList I am not getting any value in ch. I don't understand what I am doing wrong.

Following is my code:

package main
import (
&quot;database/sql&quot;
&quot;fmt&quot;
&quot;net/http&quot;
_ &quot;github.com/go-sql-driver/mysql&quot;
&quot;log&quot;
)
var db *sql.DB
func getdataList(id int) {
ch := make(chan interface{})
done := make (chan bool)
RunQuery(ch,&quot;select id,name, last_name,first_name from persons where id= ?&quot;, id)
go func() {
for {
x, ok := &lt;-ch //I am not getting any data in channel here
if ok {
fmt.Println(x)
}else {
fmt.Println(&quot;done&quot;)
done &lt;- 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(&quot;Failed to get columns&quot;, 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 &lt; count; i++ {
valuePtrs[i] = &amp;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 &lt;- tableData
}
func dbtest(w http.ResponseWriter, req *http.Request) {
go getdataList(2)
go getdataList(3)
}
func main() {
var err error
db, err = sql.Open(&quot;mysql&quot;, &quot;root:@/dbName&quot;)
if err != nil {
panic(err.Error())  
}
defer db.Close()
http.HandleFunc(&quot;/dbTest&quot;, dbtest)
log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))
}

答案1

得分: 1

你的代码问题在于它在数据从通道中读取之前阻塞了执行流程。当你从getdataList调用RunQuery时,RunQuery试图通过通道ch发送数据。然而,没有任何地方从ch中读取数据,因为读取代码位于getdataList中,并且在调用RunQuery之后。

因此,RunQuery永远不会返回,而从ch读取的goroutine也永远不会触发。为了修复这个问题,你可以尝试将RunQuery也作为一个goroutine运行:

func getdataList(id int) {
    ch := make(chan interface{})
    done := make(chan bool)
    // 在一个goroutine中运行
    go RunQuery(ch, "select id,name, last_name,first_name from persons where id= ?", id)
    go func() {
        for {
            x, ok := <-ch // 这里我没有收到任何通道中的数据
            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)
}
英文:

The problem with your code is that it is blocking the execution flow before data can be read from the channel. When you call RunQuery from getdataList, RunQuery tries to send data over channel ch. However, nothing is reading from ch because the code to read from it is in getdataList and it's below the call to RunQuery.

Therefore, RunQuery never returns and the goroutine to read from ch never fires. To fix, You can try running RunQuery as a goroutine as well:

func getdataList(id int) {
ch := make(chan interface{})
done := make (chan bool)
// run in a goroutine
go RunQuery(ch,&quot;select id,name, last_name,first_name from persons where id= ?&quot;, id)
go func() {
for {
x, ok := &lt;-ch //I am not getting any data in channel here
if ok {
fmt.Println(x)
}else {
fmt.Println(&quot;done&quot;)
done &lt;- true
return
}
}
}()
}

There is another issue in your code. You are never closing ch. This may result in deadlock. The most ideal place to do this appears to be in RunQuery:

func RunQuery (ch chan interface{}, query string, param interface{}) {
// ...
ch &lt;- tableData
close(ch)
}

huangapple
  • 本文由 发表于 2016年8月24日 16:04:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/39117702.html
匿名

发表评论

匿名网友

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

确定