英文:
How to iterate over []map[string]interface{} in Go to generate html table
问题
我正在尝试使用Go
中的html/template
生成HTML内容。数据实际上是来自不同MySQL
表的SELECT
查询的输出。
我需要以下方面的帮助:
- 我能够生成HTML,但无法拆分行。如何迭代
result := []map[string]interface{}{}
(我使用接口,因为在执行之前无法确定列数和类型),以表格格式呈现数据? - 列和行不匹配
注意:当前播放链接中的result
包含2个映射,应视为动态的。它将根据目标表格而变化。
这是一个播放链接,其中包含与我的用例相匹配的示例数据。
https://go.dev/play/p/UTL_j1iRyoG
以下是输出的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>
英文:
Am trying to generate a HTML content using html/template
in Go
. The data is actually an output of SELECT
query from different MySQL
Tables.
I need help on the below
- Am able to generate the HTML but am unable to split the rows. How to iterate over
result := []map[string]interface{}{}
(I use interface since the number of columns and it's type are unknown prior to execution) to present data in a table format ? - The Columns and Rows aren't matching
Note: Currently result
in the playground link contains 2 maps which should be considered as dynamic. It will change depending on the target table.
Here is the playground link which has sample data matching my use case.
https://go.dev/play/p/UTL_j1iRyoG
Below is the output HTML which adds all the values as single row which also doesn't match with Columns.
<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
得分: 0
你可以按照以下方式进行操作:
var cols []string
var rows [][]interface{}
for key, _ := range result[0] {
cols = append(cols, key)
}
for _, res := range result {
vals := make([]interface{}, len(cols))
for i, col := range cols {
vals[i] = res[col]
}
rows = append(rows, vals)
}
data := struct {
Title string
Columns []string
Rows [][]interface{}
}{
Title: "My page",
Columns: cols,
Rows: rows,
}
并且需要相应地修改 HTML:
<table>
<tr>
{{range .Columns}}<th>{{ . }}</th>{{else}}<div><strong>no rows</strong></div>{{end}}
</tr>
{{- range .Rows}}
<tr>
{{range .}}<td>{{ . }}</td>{{end}}
</tr>
{{- end}}
</table>
请注意,在 Go 中,映射是无序的,因此在循环遍历 result[0]
以聚合列名时,会产生无序的 []string
。这意味着多次查看 HTML 页面的用户将看到不一致的输出。如果你想避免这种情况,可以选择使用 sort
包对列进行排序,或者以某种方式保留 sql.Rows.Columns
的顺序。
英文:
You can do the following:
var cols []string
var rows [][]interface{}
for key, _ := range result[0] {
cols = append(cols, key)
}
for _, res := range result {
vals := make([]interface{}, len(cols))
for i, col := range cols {
vals[i] = res[col]
}
rows = append(rows, vals)
}
data := struct {
Title string
Columns []string
Rows [][]interface{}
}{
Title: "My page",
Columns: cols,
Rows: rows,
}
And the HTML will need to be modified accordingly:
<table>
<tr>
{{range .Columns}}<th>{{ . }}</th>{{else}}<div><strong>no rows</strong></div>{{end}}
</tr>
{{- range .Rows}}
<tr>
{{range .}}<td>{{ . }}</td>{{end}}
</tr>
{{- end}}
</table>
https://go.dev/play/p/MPJOMlfQ488
Note that in Go maps are unordered, so looping over result[0]
to aggregate the column names will produce an unordered []string
. This means that the user viewing your HTML page multiple times will see inconsistent output. If that's something you want to avoid, you could either choose to sort the columns using package sort
, or you could opt to retain the order of sql.Rows.Columns
in some way.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论