如何在Go模板中分配一个变量给另一个Go模板?

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

How to assign a variable of a go template inside a go template?

问题

我刚开始使用golang和模板系统来重新开发我的Web服务器。现在我只想为每个网站编写常量变量,但我实际上并不知道我在搜索什么。希望有人可以帮助我。

我有一个用于每个HTML文件的"base"的gohtml文件:

    {{define "topdoc"}}
    <!DOCTYPE html>
    <html lang="en" data-bs-theme="dark">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>{{.title}}</title>
        <!-- Bootstrap -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet"
              integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ"
              crossorigin="anonymous">
    </head>
    <body>
{{end}}

{{define "botdoc"}}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe"
            crossorigin="anonymous"></script>
    </body>
    </html>
{{end}}

然后我想以相同的方式更改标题,以及以后的元数据描述等等。

{{template "topdoc" .}}
{{template "navbar"}}
HOME

{{template "botdoc"}}

Navbar在另一个文件中定义。

现在我想在这个文件中传递变量,例如:

{{template "topdoc" .title="Home" .otherParam="Checking..."}}
{{template "navbar"}}
HOME

{{template "botdoc"}}

也许有人可以帮我解决这个非常琐碎的问题。

当我使用这种方法时:

{{define "title"}}Home{{end}}
{{template "topdoc"}}
{{template "navbar"}}
HOME

{{template "botdoc"}}

并首先加载基础文件时,它显示一个空白网站。

我像这样加载模板文件:

func main() {
	r := gin.Default()

	tmpl = make(map[string]*template.Template)

	// 加载模板文件
	templateFiles := []string{}

	fmt.Println("加载模板文件...")
	// 遍历"templates"文件夹及其所有子目录
	nerr := filepath.Walk("main/web/assets/templates", func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 检查文件是否为HTML模板
		if !info.IsDir() && strings.HasSuffix(info.Name(), ".gohtml") {
			// 将反斜杠替换为正斜杠(用于兼容Windows)
			templateName := strings.Replace(path, "\\", "/", -1)

			// 解析文件并将其添加到"tmpl"映射中
			templateFiles = append(templateFiles, path)

			//console log
			fmt.Print(templateName + " ")
		}
		return nil
	})

	if nerr != nil {
		panic(nerr)
	}

	fmt.Println("\n\n加载网站...")
	// 遍历"public"文件夹及其所有子目录
	err := filepath.Walk("main/web/public", func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 检查文件是否为HTML模板
		if !info.IsDir() && strings.HasSuffix(info.Name(), ".gohtml") {
			// 获取目录路径(相对于"public"文件夹)
			relPath, err := filepath.Rel("main/web/public", filepath.Dir(path))
			if err != nil {
				return err
			}
			// 将反斜杠替换为正斜杠(用于兼容Windows)
			templateName := strings.Replace(relPath, "\\", "/", -1)

			// 解析文件并将其添加到"tmpl"映射中
			parsing := []string{}
			parsing = append(parsing, templateFiles...)
			parsing = append(parsing, path)

			fmt.Println(parsing)

			tmpl[templateName] = template.Must(template.ParseFiles(parsing...))

			// 如果路径为空,则默认为"index"
			if templateName == "." {
				templateName = ""
			}

			// 使用适当的路由注册模板
			r.GET("/"+templateName, handler)
		}

		return nil
	})
	if err != nil {
		panic(err)
	}

	r.Run()
}
英文:

I'm just starting to use golang and the template system to redevelop my webserver. Now I just want to write constant variables for each website but I don't even really know what I'm searching. I hope some one can help.

I have this gohtml file for the "base" of every html File

    {{define &quot;topdoc&quot;}}
    &lt;!DOCTYPE html&gt;
    &lt;html lang=&quot;en&quot; data-bs-theme=&quot;dark&quot;&gt;
    &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;&gt;
        &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;
        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;
        &lt;title&gt;{{.title}}&lt;/title&gt;
        &lt;!-- Bootstrap --&gt;
        &lt;link href=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot;
              integrity=&quot;sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ&quot;
              crossorigin=&quot;anonymous&quot;&gt;
    &lt;/head&gt;
    &lt;body&gt;
{{end}}

{{define &quot;botdoc&quot;}}
    &lt;script src=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js&quot;
            integrity=&quot;sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe&quot;
            crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;
    &lt;/body&gt;
    &lt;/html&gt;
{{end}}

Than I want to change the title and later for example meta data description and stuff like that the same way.

{{template &quot;topdoc&quot; .}}
{{template &quot;navbar&quot;}}
HOME
{{template &quot;botdoc&quot;}}

Navbar is defined in another file.

Now I want to give the variable in this file like

{{template &quot;topdoc&quot; .title=&quot;Home&quot; .otherParam=&quot;Checking...&quot;}}
{{template &quot;navbar&quot;}}
HOME
{{template &quot;botdoc&quot;}}

Maybe someon can help me with this very trivial issue.

When I use this method

{{define &quot;title&quot;}}Home{{end}}
{{template &quot;topdoc&quot;}}
{{template &quot;navbar&quot;}}
HOME
{{template &quot;botdoc&quot;}}

And load the base file first, it shows a blank website.

I load the template files like this:

func main() {
	r := gin.Default()

	tmpl = make(map[string]*template.Template)

	// Load templates files
	templateFiles := []string{}

	fmt.Println(&quot;Loading templates...&quot;)
	// Walk through the &quot;templates&quot; folder and all its subdirectories
	nerr := filepath.Walk(&quot;main/web/assets/templates&quot;, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// Check if the file is an HTML templates
		if !info.IsDir() &amp;&amp; strings.HasSuffix(info.Name(), &quot;.gohtml&quot;) {
			// Replace backslashes with forward slashes (for Windows compatibility)
			templateName := strings.Replace(path, &quot;\\&quot;, &quot;/&quot;, -1)

			// Parse the file and add it to the &quot;tmpl&quot; map
			templateFiles = append(templateFiles, path)

			//console log
			fmt.Print(templateName + &quot; &quot;)
		}
		return nil
	})

	if nerr != nil {
		panic(nerr)
	}

	fmt.Println(&quot;\n\nLoading sites...&quot;)

	// Walk through the &quot;public&quot; folder and all its subdirectories
	err := filepath.Walk(&quot;main/web/public&quot;, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// Check if the file is an HTML templates
		if !info.IsDir() &amp;&amp; strings.HasSuffix(info.Name(), &quot;.gohtml&quot;) {
			// Get the directory path (relative to the &quot;public&quot; folder)
			relPath, err := filepath.Rel(&quot;main/web/public&quot;, filepath.Dir(path))
			if err != nil {
				return err
			}
			// Replace backslashes with forward slashes (for Windows compatibility)
			templateName := strings.Replace(relPath, &quot;\\&quot;, &quot;/&quot;, -1)

			// Parse the file and add it to the &quot;tmpl&quot; map
			parsing := []string{}
			parsing = append(parsing, templateFiles...)
			parsing = append(parsing, path)

			fmt.Println(parsing)

			tmpl[templateName] = template.Must(template.ParseFiles(parsing...))

			// If the path is empty, default to &quot;index&quot;
			if templateName == &quot;.&quot; {
				templateName = &quot;&quot;
			}

			// Register the templates with the appropriate route
			r.GET(&quot;/&quot;+templateName, handler)
		}

		return nil
	})
	if err != nil {
		panic(err)
	}

	r.Run()
}

答案1

得分: 1

这通常是通过模板组合来实现的。在你的“topdoc”模板中,只需调用其他模板:

{{define "topdoc"}}
...
{{template "title"}}
...
{{end}}

并将“title”模板定义为

{{define "title"}}默认标题{{end}}

然后,你可以在单独的文件中重新定义“title”模板来覆盖它:

{{define "title"}}新标题{{end}}
{{define "someTemplate"}}
{{template "topdoc"}}
...
{{end}}

你需要组合这些不同的模板文件,以便首先加载“topdoc”(它定义了默认的“title”),然后加载重新定义“title”的模板。

英文:

This is usually achieved using template composition. In your "topdoc" template, simply call other templates:

{{define &quot;topdoc&quot;}}
...
{{template &quot;title&quot;}}
...
{{end}}

And define the "title" template as

{{define &quot;title&quot;}}Default title{{end}}

Then, you can override the "title" template with a redefinition of it in a separate file:

{{define &quot;title&quot;}}New title{{end}}
{{define &quot;someTemplate}}
{{template &quot;topdoc&quot;}}
...
{{end}}

You have to compose these different template files so that you load the "topdoc" first (which defines the default "title"), and then load the template redefining the "title".

答案2

得分: 0

为了在Go模板中使用“常量”,最简单的方法是使用模板来定义它们。因此,首先加载基本模板文件非常重要,以便可以进行覆盖。在这样做时,定义一个“content”模板非常重要,以便可以显示实际的网站内容。

因此,base.golang文件的内容如下:

{{define "topdoc"}}
    <!DOCTYPE html>
    <html lang="eng" data-bs-theme="dark">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>{{template "title"}}</title>
        <!-- Bootstrap -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet"
              integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ"
              crossorigin="anonymous">
    </head>
    <body>
{{end}}

{{define "title"}} Default Title {{end}}
{{template "content"}}

{{define "botdoc"}}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe"
            crossorigin="anonymous"></script>
    </body>
    </html>
{{end}}

网站文件的内容如下:

{{define "title"}}Home{{end}}
{{define "content"}}
{{template "topdoc"}}


{{template "navbar"}}
Home

{{template "botdoc"}}
{{end}}
英文:

In order to use "constants" in go templates, its the easiest way to just use a template to define them.
Therefor its important to load the base template file at first, so it can be overriten.
When doing that, its important to define a "content" template, so that the actual website can be displayed.

So the base.golang would look like this

{{define &quot;topdoc&quot;}}
    &lt;!DOCTYPE html&gt;
    &lt;html lang=&quot;eng&quot; data-bs-theme=&quot;dark&quot;&gt;
    &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;&gt;
        &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;
        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;
        &lt;title&gt;{{template &quot;title&quot;}}&lt;/title&gt;
        &lt;!-- Bootstrap --&gt;
        &lt;link href=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot;
              integrity=&quot;sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ&quot;
              crossorigin=&quot;anonymous&quot;&gt;
    &lt;/head&gt;
    &lt;body&gt;
{{end}}

{{define &quot;title&quot;}} Default Title {{end}}
{{template &quot;content&quot;}}

{{define &quot;botdoc&quot;}}
    &lt;script src=&quot;https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js&quot;
            integrity=&quot;sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe&quot;
            crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;
    &lt;/body&gt;
    &lt;/html&gt;
{{end}}

The website file would thant look like this

{{define &quot;title&quot;}}Home{{end}}
{{define &quot;content&quot;}}
{{template &quot;topdoc&quot;}}


{{template &quot;navbar&quot;}}
Home

{{template &quot;botdoc&quot;}}
{{end}}

huangapple
  • 本文由 发表于 2023年5月12日 03:54:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76231211.html
匿名

发表评论

匿名网友

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

确定