You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go中遍历[]map[string]interface{}生成HTML表格的问题求助

在Go中用html/template动态生成MySQL查询结果表格的问题与解决

问题描述

我在Go里用html/template生成HTML,数据来自不同MySQL表的查询结果,碰到两个问题:

  • 能生成HTML但没法拆分数据行,不知道怎么遍历[]map[string]interface{}类型的result(因为执行前不知道列的数量和类型,所以用了interface)来生成表格
  • 表格的列和行对应不上,当前输出把所有值堆在一行里

当前错误输出的HTML:

<html>
    <head>
        <meta charset="UTF-8">
        <title>My page</title>
        <style>
        table, th, td {
          border: 1px solid black;
        }
        th, td {
          padding: 10px;
        }
        </style>
    </head>
    <body>
    <table>
        <tr>
        <th>Name</th><th>Colour</th>
        </tr>
        <tr>
        <td>Red</td><td>Apple</td><td>Banana</td><td>Yellow</td>
        </tr>
    </table>
    </body>
</html>

解决方案

核心思路

  1. 动态提取表头:从result的第一个map中取出所有key作为列名,避免硬编码表头
  2. 按表头顺序遍历行数据:对每一行,严格按照表头的顺序取值,保证列和行的对应关系

完整实现代码

package main

import (
	"html/template"
	"os"
)

func main() {
	// 模拟MySQL查询返回的动态结果
	result := []map[string]interface{}{
		{"Name": "Apple", "Colour": "Red"},
		{"Name": "Banana", "Colour": "Yellow"},
	}

	// 提取表头:如果结果不为空,取第一个map的键作为列名
	var headers []string
	if len(result) > 0 {
		for col := range result[0] {
			headers = append(headers, col)
		}
	}

	// 定义模板
	tableTmpl := template.Must(template.New("dynamicTable").Parse(`
<html>
    <head>
        <meta charset="UTF-8">
        <title>Query Result</title>
        <style>
        table, th, td {
          border: 1px solid #ccc;
          border-collapse: collapse;
        }
        th, td {
          padding: 8px 12px;
          text-align: left;
        }
        th {
          background-color: #f5f5f5;
        }
        </style>
    </head>
    <body>
    {{if .Rows}}
    <table>
        <tr>
            {{range .Headers}}<th>{{.}}</th>{{end}}
        </tr>
        {{range .Rows}}
        <tr>
            {{range $col := $.Headers}}<td>{{index . $col}}</td>{{end}}
        </tr>
        {{end}}
    </table>
    {{else}}
    <p>No data found</p>
    {{end}}
    </body>
</html>
	`))

	// 准备模板数据:封装表头和行数据
	tmplData := struct {
		Headers []string
		Rows    []map[string]interface{}
	}{
		Headers: headers,
		Rows:    result,
	}

	// 执行模板并输出
	if err := tableTmpl.Execute(os.Stdout, tmplData); err != nil {
		panic(err)
	}
}

代码说明

  • 表头提取:通过遍历第一个map的key获取列名,适配不同表的动态结构
  • 模板遍历逻辑:
    • 先用{{range .Headers}}生成表头行
    • 再遍历每一行数据{{range .Rows}},对每一行,用{{index . $col}}按照表头顺序取出对应的值,确保列和行完全匹配
  • 空数据处理:用{{if .Rows}}判断是否有数据,避免生成空表格

额外提示

  • 如果需要固定列的顺序,可以在提取表头后对headers切片进行排序,或者在MySQL查询时明确指定列的顺序
  • 若处理大量数据,可考虑分页,避免一次性渲染过多内容

内容的提问来源于stack exchange,提问作者Gopi Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 03:03:23