簡體   English   中英

MySql在golang中類型接口的通道不接收值

[英]channel of type interface not receiving value in golang with MySql

我是golang的新手。 我正在嘗試使用golang對mysql db進行並發查詢。 我知道通道可以是類型接口。 當我在RunQuery函數中打印tableData (type map)時,得到了結果。 我正在發送tableDatach即類型接口的通道。 在函數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))

}

您的代碼的問題在於,在可以從通道讀取數據之前,它阻塞了執行流程。 當從getdataList調用RunQuery時, RunQuery嘗試通過通道ch發送數據。 但是,從ch不會讀取任何內容,因為要從ch讀取的代碼位於getdataList ,並且位於對RunQuery的調用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)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM