如何在Go中迭代[]map[string]interface{}以生成HTML表格

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

How to iterate over []map[string]interface{} in Go to generate html table

问题

我正在尝试使用Go中的html/template生成HTML内容。数据实际上是来自不同MySQL表的SELECT查询的输出。

我需要以下方面的帮助:

  1. 我能够生成HTML,但无法拆分行。如何迭代result := []map[string]interface{}{}(我使用接口,因为在执行之前无法确定列数和类型),以表格格式呈现数据?
  2. 列和行不匹配

注意:当前播放链接中的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

  1. 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 ?
  2. 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:   &quot;My page&quot;,
	Columns: cols,
	Rows:    rows,
}

And the HTML will need to be modified accordingly:

&lt;table&gt;
    &lt;tr&gt;
    {{range .Columns}}&lt;th&gt;{{ . }}&lt;/th&gt;{{else}}&lt;div&gt;&lt;strong&gt;no rows&lt;/strong&gt;&lt;/div&gt;{{end}}
    &lt;/tr&gt;
    {{- range .Rows}}
    &lt;tr&gt;
    {{range .}}&lt;td&gt;{{ . }}&lt;/td&gt;{{end}}
    &lt;/tr&gt;
    {{- end}}
&lt;/table&gt;

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.

huangapple
  • 本文由 发表于 2022年7月27日 01:38:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/73127597.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定