Golang中{{range.}}为什么不起作用?
Golang中{{range.}}为什么不起作用? 我正在尝试理解HTML模板如何与JSON配合工作。找到了一个示例:
https://play.golang.org/p/EOVypH5ONHn
…并尝试向其添加 {{range.}},但出现了错误:
https://play.golang.org/p/vrwx01z0_0o
package main
import (
"encoding/json"
"html/template"
"os"
)
func main() {
t := template.Must(template.New("").Parse(templ))
m := map[string]interface{}{}
if err := json.Unmarshal([]byte(jsondata), &m); err != nil {
panic(err)
}
if err := t.Execute(os.Stdout, m); err != nil {
panic(err)
}
}
const templ = `<html><body>
{{range.}}
{{.something}}
{{.somethingElse}}
{{end}}
</body></html>`
const jsondata = `{"something":"valueofa", "somethingElse": 1234}`
我哪里做错了?为什么没有 {{range.}} 时它可以正常工作?
更多关于Golang中{{range.}}为什么不起作用?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
请注意,该模板处理的是 JSON 数组。即使你只有一个 JSON 对象,也必须将其包装成 JSON 数组,此模板才能正常工作。
更多关于Golang中{{range.}}为什么不起作用?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
如果你想遍历JSON对象中的项目,可以这样做:
const templ = `<html><body>
{{ range $key, $value := . }}
<li>{{ $key }}: {{ $value }}</li>
{{ end }}
</body></html>`
输出:
<html><body>
<li>something: valueofa</li>
<li>somethingElse: 1234</li>
</body></html>
你期望得到什么样的HTML输出?
另外请注意
{"something":"valueofa", "somethingElse": 1234},
{"something":"valueofb", "somethingElse": 3456}
不是有效的JSON。你可以将这两个对象包装到一个JSON数组中:
[
{"something":"valueofa", "somethingElse": 1234},
{"something":"valueofb", "somethingElse": 3456}
]
你需要将
m := map[string]interface{}{}
改为
m := []map[string]interface{}{}
// ^^ -- 数组!
并将模板改为
const templ = `<html><body>
{{ range . }}
<li>{{ .something }}: {{ .somethingElse }}</li>
{{ end }}
</body></html>`
输出:
<html><body>
<li>valueofa: 1234</li>
<li>valueofb: 3456</li>
</body></html>
{{range.}} 不起作用是因为你错误地使用了 range 动作。在 Go 模板中,{{range}} 用于迭代数组、切片、map 或 channel,但你的数据是 map 类型,而 {{range.}} 中的点号 . 代表当前上下文(整个 map),这会导致模板引擎尝试迭代 map 的键值对。
在你的代码中,{{range.}} 会迭代 map 的每个键值对,而每次迭代中的 . 会变成当前迭代的值(可能是字符串或数字)。当模板尝试执行 {{.something}} 时,实际上是在字符串或数字上查找 something 字段,这会导致错误。
以下是修正后的代码:
package main
import (
"encoding/json"
"html/template"
"os"
)
func main() {
t := template.Must(template.New("").Parse(templ))
m := map[string]interface{}{}
if err := json.Unmarshal([]byte(jsondata), &m); err != nil {
panic(err)
}
if err := t.Execute(os.Stdout, m); err != nil {
panic(err)
}
}
const templ = `<html><body>
{{.something}}
{{.somethingElse}}
</body></html>`
const jsondata = `{"something":"valueofa", "somethingElse": 1234}`
如果你确实需要迭代 map 的键值对,可以这样写:
const templ = `<html><body>
{{range $key, $value := .}}
Key: {{$key}}, Value: {{$value}}
{{end}}
</body></html>`
或者如果你有一个数组/切片需要迭代:
package main
import (
"encoding/json"
"html/template"
"os"
)
func main() {
t := template.Must(template.New("").Parse(templ))
var data []map[string]interface{}
if err := json.Unmarshal([]byte(jsondata), &data); err != nil {
panic(err)
}
if err := t.Execute(os.Stdout, data); err != nil {
panic(err)
}
}
const templ = `<html><body>
{{range .}}
{{.something}}
{{.somethingElse}}
{{end}}
</body></html>`
const jsondata = `[
{"something":"value1", "somethingElse": 1234},
{"something":"value2", "somethingElse": 5678}
]`
在你的原始代码中,当没有 {{range.}} 时,点号 . 直接代表整个 map,所以 {{.something}} 能够正确访问 map 中的 “something” 键。


