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

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

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

问题

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

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

package model

import "database/sql"
import "hb-backend-v1/config/database"
import "fmt"

func Query(query string) (*sql.Rows, error){
    connect, err := database.Connect()

    if err != nil{
        fmt.Println("连接失败")
        return nil, err
    }
    fmt.Println("连接成功")
    defer connect.Close()

    rows, err := connect.Query(query)

    defer rows.Close()
    if err != nil{
        return nil, err
    }

    return rows, nil
}

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

package product

import "database/sql"
import _ "fmt"
import "hb-backend=v1/model"

type Hasil struct{
    Id_alamat_store int
    Id_tk           int
    Alamat          string
    Id_wil          int
    Latitude        sql.NullString
    Longitude       sql.NullString
    
}

func ProductList() ([]Hasil, error){
    rows, err := model.Query("SELECT * FROM alamat_store")
    if err != nil{
        return nil, err
    }
    
    var result []Hasil
    for rows.Next(){
        var each = Hasil{}
        var err = rows.Scan(&each.Id_alamat_store, &each.Id_tk, &each.Alamat, &each.Id_wil, &each.Latitude, &each.Longitude)
        if err != nil{
            return nil, err
        }
        result = append(result, each)
    }
    return result, nil
}
英文:

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

package model

import "database/sql"
import "hb-backend-v1/config/database"
import "fmt"

func Query(query string) (*sql.Rows, error){
	connect, err := database.Connect()

	if err != nil{
		fmt.Println("Connection Failed")
		return nil, err
	}
	fmt.Println("Connection Success")
	defer connect.Close()

	rows, err := connect.Query(query)

	defer rows.Close()
	if err != nil{
		return nil, err
	}

	return rows, nil
}

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

package product

import "database/sql"
import _"fmt"
import "hb-backend=v1/model"

type Hasil struct{
	Id_alamat_store int
	Id_tk 			int
	Alamat 			string
	Id_wil 			int
	Latitude 		sql.NullString
	Longitude 		sql.NullString
	
}

func ProductList() ([]Hasil, error){
	rows, err := model.Query("SELECT * FROM alamat_store")
	if err != nil{
		return nil, err
	}
	
	var result []Hasil
	for rows.Next(){
		var each = Hasil{}
		var err = rows.Scan(&each.Id_alamat_store, &each.Id_tk, &each.Alamat, &each.Id_wil, &each.Latitude, &each.Longitude)
		if err != nil{
			return nil, err
		}
		result = append(result, each)
	}
	return result, nil
}

答案1

得分: 1

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

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

func Query(query string, scan func(*sql.Rows) error) error {
    connect, err := database.Connect()
    if err != nil{
        return err
    }
    defer connect.Close()

    rows, err := connect.Query(query)
    if err != nil{
        return err
    }
    defer rows.Close()

    return scan(rows)
}
func ProductList() ([]Hasil, error) {
	var result []Hasil
	err := model.Query("SELECT * FROM alamat_store", func(rows *sql.Rows) error {
		for rows.Next() {
			var each = Hasil{}
			var err = rows.Scan(&each.Id_alamat_store, &each.Id_tk, &each.Alamat, &each.Id_wil, &each.Latitude, &each.Longitude)
			if err != nil {
				return err
			}
			result = append(result, each)
		}
        return nil
	})
	if err != nil {
		return nil, err
	}
	return result, nil
}
英文:

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:

func Query(query string, scan func(*sql.Rows) error) error {
    connect, err := database.Connect()
    if err != nil{
        return err
    }
    defer connect.Close()

    rows, err := connect.Query(query)
    if err != nil{
        return err
    }
    defer rows.Close()

    return scan(rows)
}
func ProductList() ([]Hasil, error) {
	var result []Hasil
	err := model.Query("SELECT * FROM alamat_store", func(rows *sql.Rows) error {
		for rows.Next() {
			var each = Hasil{}
			var err = rows.Scan(&each.Id_alamat_store, &each.Id_tk, &each.Alamat, &each.Id_wil, &each.Latitude, &each.Longitude)
			if err != nil {
				return err
			}
			result = append(result, each)
		}
        return nil
	})
	if err != nil {
		return nil, err
	}
	return result, nil
}

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:

确定