我正在使用go开发一个webapi,其中有很多冗余的数据库查询扫描代码。
func (m *ContractModel) WorkQuestions(cid int) ([]models.WorkQuestion, error) {
results, err := m.DB.Query(queries.WORK_QUESTIONS, cid)
if err != nil {
return nil, err
}
var workQuestions []models.WorkQuestion
for results.Next() {
var wq models.WorkQuestion
err = results.Scan(&wq.ContractStateID, &wq.QuestionID, &wq.Question, &wq.ID, &wq.Answer, &wq.Compulsory)
if err != nil {
return nil, err
}
workQuestions = append(workQuestions, wq)
}
return workQuestions, nil
}
func (m *ContractModel) Questions(cid int) ([]models.Question, error) {
results, err := m.DB.Query(queries.QUESTIONS, cid)
if err != nil {
return nil, err
}
var questions []models.Question
for results.Next() {
var q models.Question
err = results.Scan(&q.Question, &q.Answer)
if err != nil {
return nil, err
}
questions = append(questions, q)
}
return questions, nil
}
func (m *ContractModel) Documents(cid int) ([]models.Document, error) {
results, err := m.DB.Query(queries.DOCUMENTS, cid)
if err != nil {
return nil, err
}
var documents []models.Document
for results.Next() {
var d models.Document
err = results.Scan(&d.Document, &d.S3Region, &d.S3Bucket, &d.Source)
if err != nil {
return nil, err
}
documents = append(documents, d)
}
return documents, nil
}
我需要对这个代码进行泛化,以便传入结果 *sql.Rows
并获取包含扫描行的结构片。我知道有一个 StructScan
方法,但这不能使用,因为我有大量使用go标准数据库/sql包编写的代码。
使用reflect包,我可以创建一个泛型structscan函数,但是reflect包不能从传递的接口{}类型创建一个结构片。我需要达到的目标如下
func RowsToStructs(rows *sql.Rows, model interface{}) ([]interface{}, error) {
// 1. Create a slice of structs from the passed struct type of model
// 2. Loop through each row,
// 3. Create a struct of passed mode interface{} type
// 4. Scan the row results to a slice of interface{}
// 5. Set the field values of struct created in step 3 using the slice in step 4
// 6. Add the struct created in step 3 to slice created in step 1
// 7. Return the struct slice
}
我似乎找不到一种方法来扫描作为模型参数传递的结构,并使用reflect包创建它的一个片段。有什么解决办法吗?还是我看问题的方式不对?
结构字段具有从结果返回的正确列数,并且顺序正确
2条答案
按热度按时间niknxzdl1#
通过将指向目标片的指针作为参数传递,可以避免在调用函数中使用类型Assert。下面是经过修改的rowstostructs:
这样称呼:
通过将查询移动到助手函数来消除更多样板文件:
这样称呼:
bq8i3lrv2#
"... 但是reflect包无法从传递的接口{}类型创建结构片?
https://play.golang.com/p/o4aj-f71egw
“我要达到的目标如下”
或者你在找这个?
https://play.golang.com/p/i57z8oo8n7g