Golang模板中如何显示sqlx.StructScan的结果键值

Golang模板中如何显示sqlx.StructScan的结果键值 如果我使用这种不太符合惯用法的方式,值会在Go模板中显示出来。

var list []map[string]interface{}
	rows, err := db.Queryx("SELECT hr_id, hr_sign, hr_code, hr_sum FROM hr")

	if err != nil {
		log("get error" + err.Error())
	}

	defer rows.Close()

	for rows.Next() {
		row := make(map[string]interface{})
		err = rows.MapScan(row)
		if err != nil {
			log("next " + err.Error())
		}
		list = append(list, row)
	}

结果将同时包含键和值:

[map[hr_code:PM hr_date:2020-08-26 00:00:00 +0000 +0000 hr_id:135 hr_job:20-0002 hr_ppu:[49 48 48 48 46 48 48] hr_qty:[48 46 50 53] hr_sign:JD hr_subject:test hr_sum:[50 53 48 46 48 48]] map[hr_code:PM hr_date:2020-08-26 00:00:00 +0000 +0000 hr_id:138 hr_job:20-0002 hr_ppu:[49 48 48 48 46 48 48] hr_qty:[49 46 48 48] hr_sign:JD hr_subject:test hr_sum:[49 48 48 48 46 48 48]]]

尝试使用结构体这种更符合惯用法的方式:

type Hr struct {
	Hr_id   int     `db:"hr_id"`
	Hr_sign string  `db:"hr_sign"`
	Hr_code string  `db:"hr_code"`
	Hr_sum  float64 `db:"hr_sum"`
}

rows, err := db.Queryx("SELECT hr_id, hr_sign, hr_code, hr_sum FROM hr")
defer rows.Close()
result := []Hr{}
for rows.Next() {
	row := Hr{}
	err := rows.StructScan(&row)
	if err != nil {
		log("getsql error" + err.Error())
	}
	result = append(result, row)
}

fmt.Println(result)

只有值出现了。没有键。并且Go模板什么也不显示。

[{135 JD PM 250} {138 JD PM 1000} {139 JD PM 1250} {140 JD PM 250} {141 JD PM 250} {142 JD PM 1250} {143 JD PM 1250} {144 JD PM 1250} {145 JD PM 1250} {146 JD PM 1250} {147 JD PM 1250} {148 JD PM 250} {149 JD PM 250} {150 JD PM 250} {151 JD PM 250} {152 JD PM 250} {153 JD PM 250} {154 JD PM 500} {155 JD PM 500} {156 JD PM 500} {157 JD PM 750} {158 JD PM 750} {159 JD PM 750} {160 JD PM 750} {161 JD PM 750}]

我哪里做错了?


更多关于Golang模板中如何显示sqlx.StructScan的结果键值的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

Hr 实现 Stringer 接口:

type Stringer interface {
    String() string
}

像这样:

package main

import (
	"fmt"
)

type Hr struct {
	Hr_id   int     `db:"hr_id"`
	Hr_sign string  `db:"hr_sign"`
	Hr_code string  `db:"hr_code"`
	Hr_sum  float64 `db:"hr_sum"`
}

func (hr Hr) String() string {
	return fmt.Sprintf("ID=%d, Sign=%s, Code=%s, Sum=%f", hr.Hr_id, hr.Hr_sign, hr.Hr_code, hr.Hr_sum)
}

func main() {
	hr := Hr{Hr_id: 123, Hr_sign: "The Sign", Hr_code: "The Code", Hr_sum: 1.234}
	fmt.Println(hr)
}

输出:

ID=123, Sign=The Sign, Code=The Code, Sum=1.234000

参见 https://play.golang.org/p/4dVU4wcHYSh

我建议重命名 Hr 的属性:

type Hr struct {
	Id   int     `db:"hr_id"`
	Sign string  `db:"hr_sign"`
    Code string  `db:"hr_code"`
	Sum  float64 `db:"hr_sum"`
}

这将使你的代码更易于阅读。

更多关于Golang模板中如何显示sqlx.StructScan的结果键值的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go模板中显示sqlx.StructScan的结果时,需要正确访问结构体字段。模板引擎通过字段名(而非数据库标签)访问结构体数据。以下是解决方案:

// 1. 确保结构体字段首字母大写(公开)
type Hr struct {
    HrId   int     `db:"hr_id"`
    HrSign string  `db:"hr_sign"`
    HrCode string  `db:"hr_code"`
    HrSum  float64 `db:"hr_sum"`
}

// 2. 查询数据
rows, err := db.Queryx("SELECT hr_id, hr_sign, hr_code, hr_sum FROM hr")
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

var result []Hr
for rows.Next() {
    var row Hr
    err := rows.StructScan(&row)
    if err != nil {
        log.Fatal(err)
    }
    result = append(result, row)
}

// 3. 模板中使用字段名(而非标签名)
tmpl := `
{{range .}}
    ID: {{.HrId}}, Sign: {{.HrSign}}, Code: {{.HrCode}}, Sum: {{.HrSum}}
{{end}}`

t := template.Must(template.New("hr").Parse(tmpl))
t.Execute(os.Stdout, result)

如果需要在模板中使用不同的名称,可以添加模板标签:

type Hr struct {
    HrId   int     `db:"hr_id" template:"id"`
    HrSign string  `db:"hr_sign" template:"sign"`
    HrCode string  `db:"hr_code" template:"code"`
    HrSum  float64 `db:"hr_sum" template:"sum"`
}

// 自定义模板函数处理标签
func MapFromStruct(s interface{}) map[string]interface{} {
    v := reflect.ValueOf(s)
    t := v.Type()
    m := make(map[string]interface{})
    
    for i := 0; i < v.NumField(); i++ {
        field := t.Field(i)
        tag := field.Tag.Get("template")
        if tag != "" {
            m[tag] = v.Field(i).Interface()
        }
    }
    return m
}

// 使用示例
var mappedResult []map[string]interface{}
for _, hr := range result {
    mappedResult = append(mappedResult, MapFromStruct(hr))
}

tmpl := `
{{range .}}
    ID: {{.id}}, Sign: {{.sign}}, Code: {{.code}}, Sum: {{.sum}}
{{end}}`

对于简单的字段访问,直接使用结构体字段名即可:

<!-- 模板文件 hr_template.html -->
<table>
    <tr>
        <th>ID</th>
        <th>Sign</th>
        <th>Code</th>
        <th>Sum</th>
    </tr>
    {{range .}}
    <tr>
        <td>{{.HrId}}</td>
        <td>{{.HrSign}}</td>
        <td>{{.HrCode}}</td>
        <td>{{.HrSum}}</td>
    </tr>
    {{end}}
</table>
// 渲染模板
t := template.Must(template.ParseFiles("hr_template.html"))
t.Execute(w, result)

确保传递给模板的数据是结构体切片,模板中的字段访问使用结构体中定义的大写字段名。

回到顶部