在Golang函数中,我可以在不先扫描它的情况下返回数据库中的行结果吗?

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

Can I return rows result from db without scan it first in Golang func?

问题

我有一个使用Golang的小项目,我的计划是创建一个基础函数,该函数将从模型中调用以执行SQL查询,然后返回结果行而不先进行扫描。我使用这种方式是为了防止忘记编写defer rows.Close()和在模型中执行查询的代码更简单。我尝试过这种方式,但是当尝试打印结果时,我得到了一个空值而没有任何错误。这是我的截图。当查询执行时,结果存在,并且扫描的结果行在同一个函数中。也许我漏掉了什么?这是我的第一个问题,抱歉它太长了。谢谢。

执行SQL查询并返回结果的基础模型

  1. package model
  2. import "database/sql"
  3. import "hb-backend-v1/config/database"
  4. import "fmt"
  5. func Query(query string) (*sql.Rows, error){
  6. connect, err := database.Connect()
  7. if err != nil{
  8. fmt.Println("连接失败")
  9. return nil, err
  10. }
  11. fmt.Println("连接成功")
  12. defer connect.Close()
  13. rows, err := connect.Query(query)
  14. defer rows.Close()
  15. if err != nil{
  16. return nil, err
  17. }
  18. return rows, nil
  19. }

调用基础模型并返回结果的地方

  1. package product
  2. import "database/sql"
  3. import _ "fmt"
  4. import "hb-backend=v1/model"
  5. type Hasil struct{
  6. Id_alamat_store int
  7. Id_tk int
  8. Alamat string
  9. Id_wil int
  10. Latitude sql.NullString
  11. Longitude sql.NullString
  12. }
  13. func ProductList() ([]Hasil, error){
  14. rows, err := model.Query("SELECT * FROM alamat_store")
  15. if err != nil{
  16. return nil, err
  17. }
  18. var result []Hasil
  19. for rows.Next(){
  20. var each = Hasil{}
  21. var err = rows.Scan(&each.Id_alamat_store, &each.Id_tk, &each.Alamat, &each.Id_wil, &each.Latitude, &each.Longitude)
  22. if err != nil{
  23. return nil, err
  24. }
  25. result = append(result, each)
  26. }
  27. return result, nil
  28. }
英文:

I have mini project using Golang, my plan is make a base function which it will be called from Model to execute sql query, then return the rows result without Scan it first. I'm using this way to prevent forget write defer rows.Close() and the code for execute the Query in model more simple. I had tried this way, but when try to print the result, I got nil without any error. here my screenshoot. The result exists when the query executed and the rows result scanned are in same function. Maybe I miss something? This is my first question, sorry it's too long. Thank you

The base model where the SQL query will be executed and return the result

  1. package model
  2. import "database/sql"
  3. import "hb-backend-v1/config/database"
  4. import "fmt"
  5. func Query(query string) (*sql.Rows, error){
  6. connect, err := database.Connect()
  7. if err != nil{
  8. fmt.Println("Connection Failed")
  9. return nil, err
  10. }
  11. fmt.Println("Connection Success")
  12. defer connect.Close()
  13. rows, err := connect.Query(query)
  14. defer rows.Close()
  15. if err != nil{
  16. return nil, err
  17. }
  18. return rows, nil
  19. }

This is where the base model will be called and give the result

  1. package product
  2. import "database/sql"
  3. import _"fmt"
  4. import "hb-backend=v1/model"
  5. type Hasil struct{
  6. Id_alamat_store int
  7. Id_tk int
  8. Alamat string
  9. Id_wil int
  10. Latitude sql.NullString
  11. Longitude sql.NullString
  12. }
  13. func ProductList() ([]Hasil, error){
  14. rows, err := model.Query("SELECT * FROM alamat_store")
  15. if err != nil{
  16. return nil, err
  17. }
  18. var result []Hasil
  19. for rows.Next(){
  20. var each = Hasil{}
  21. var err = rows.Scan(&each.Id_alamat_store, &each.Id_tk, &each.Alamat, &each.Id_wil, &each.Latitude, &each.Longitude)
  22. if err != nil{
  23. return nil, err
  24. }
  25. result = append(result, each)
  26. }
  27. return result, nil
  28. }

答案1

得分: 1

connectionrowsQuery退出后将被关闭,一旦这两个被关闭,你就不能再使用rows了。

解决这个问题的一种方法是将一个闭包传递给Query,并在关闭这两个资源之前让Query执行它:

  1. func Query(query string, scan func(*sql.Rows) error) error {
  2. connect, err := database.Connect()
  3. if err != nil{
  4. return err
  5. }
  6. defer connect.Close()
  7. rows, err := connect.Query(query)
  8. if err != nil{
  9. return err
  10. }
  11. defer rows.Close()
  12. return scan(rows)
  13. }
  1. func ProductList() ([]Hasil, error) {
  2. var result []Hasil
  3. err := model.Query("SELECT * FROM alamat_store", func(rows *sql.Rows) error {
  4. for rows.Next() {
  5. var each = Hasil{}
  6. var err = rows.Scan(&each.Id_alamat_store, &each.Id_tk, &each.Alamat, &each.Id_wil, &each.Latitude, &each.Longitude)
  7. if err != nil {
  8. return err
  9. }
  10. result = append(result, each)
  11. }
  12. return nil
  13. })
  14. if err != nil {
  15. return nil, err
  16. }
  17. return result, nil
  18. }
英文:

Both connection and rows will be closed once Query exits, after those two are closed you can't use rows anymore.

One approach to get around that would be to pass a closure to Query and have Query execute it before closing the two resources:

  1. func Query(query string, scan func(*sql.Rows) error) error {
  2. connect, err := database.Connect()
  3. if err != nil{
  4. return err
  5. }
  6. defer connect.Close()
  7. rows, err := connect.Query(query)
  8. if err != nil{
  9. return err
  10. }
  11. defer rows.Close()
  12. return scan(rows)
  13. }
  1. func ProductList() ([]Hasil, error) {
  2. var result []Hasil
  3. err := model.Query("SELECT * FROM alamat_store", func(rows *sql.Rows) error {
  4. for rows.Next() {
  5. var each = Hasil{}
  6. var err = rows.Scan(&each.Id_alamat_store, &each.Id_tk, &each.Alamat, &each.Id_wil, &each.Latitude, &each.Longitude)
  7. if err != nil {
  8. return err
  9. }
  10. result = append(result, each)
  11. }
  12. return nil
  13. })
  14. if err != nil {
  15. return nil, err
  16. }
  17. return result, nil
  18. }

huangapple
  • 本文由 发表于 2021年8月31日 23:36:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/69001579.html
匿名

发表评论

匿名网友

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

确定