Golang中如何将模板保存到文件

Golang中如何将模板保存到文件 大家好!我最近一直在尝试用Go进行Web开发,并想创建一种“页面模板表单”,这样用户就可以在不深入代码并自行编辑的情况下创建页面。

我通过使用模板将表单变量插入其中来实现这一点。然而,当我尝试将模板执行到文件中时,文件似乎完全没有改变。

以下是我的Go代码:

import (
    "html/template"
    "net/http"
    "os"
    "io"
    "log"
)

type PageDetails struct {
	Content string
	Submitted bool
}

func main() {
    tmpl := template.Must(template.ParseFiles("page_template_1_form.html"))
    f, _ := os.Create("lesson.html")
    p, _ := os.Open("page_template_1_form.html")
    io.Copy(f, p)
    pageFile, err := template.ParseFiles("lesson.html")
    if (err != nil) {
    	log.Fatal("lesson not parsed correctly")
    }
    var details PageDetails;
    http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/"))))
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost {
            tmpl.Execute(w, nil)
            return
        }

        details = PageDetails{
            Content: r.FormValue("content"),
            Submitted: true,
        }
        f, err = os.OpenFile("lesson.html", os.O_WRONLY|os.O_APPEND, 0600)
        if (err != nil) {
        	log.Fatal("lesson was not able to be reopened")
        }
        //tmpl.Execute(w, details)
        err = pageFile.Execute(f, details)
        if (err != nil) {
        	log.Print("error is: ", err)
        }
    })
    err = f.Close()
    if (err != nil) {
    	log.Print("file could not be closed correctly: ", err)
    }

    http.ListenAndServe(":8080", nil)
}

以下是我的page_template_1_form.html代码:

<html>
	<head>
		<style>
			#layout div {
				background-color: white;
				border: solid 5px #003300;
				border-radius: 3px;
			}
		</style>
	</head>
	<body>
		{{if .Submitted}}
		<div id="layout" style="display: grid; grid-template-rows: repeat(10, 1fr); grid-template-columns: repeat(8, 1fr); grid-gap: 1%; width: 50vw; height: 100vh; margin: 0 auto; padding: 1%; background-color: green; grid-template-areas: 
		'content content content content content content content content'
		'content content content content content content content content'
		'content content content content content content content content'
		'content content content content content content content content'
		'content content content content content content content content'
		'content content content content content content content content'
		'content content content content content content content content'
		'content content content content content content content content'
		'content content content content content content content content'
				         '. . . footer footer . image image'">
			<div style="grid-area: content">{{.Content}}</div>
			<div style="grid-area: footer"></div>
			<img src="assets/graphics/Frog_1.svg" style="grid-row: -3/span 2; grid-column: -3/span 2">
		</div>
		{{else}}
		<form method=POST>
			<div id="layout" style="display: grid; grid-template-rows: repeat(10, 1fr); grid-template-columns: repeat(8, 1fr); grid-gap: 1%; width: 50vw; height: 100vh; margin: 0 auto; padding: 1%; background-color: green; grid-template-areas: 
	'content content content content content content content content'
	'content content content content content content content content'
	'content content content content content content content content'
	'content content content content content content content content'
	'content content content content content content content content'
	'content content content content content content content content'
	'content content content content content content content content'
	'content content content content content content content content'
	'content content content content content content content content'
			         '. . . footer footer . image image'">
				<div style="grid-area: content">
					<textarea style="width: 99%; height: 98%; max-width: 99%; max-height: 99%" name=content></textarea>
				</div>
				<div style="grid-area: footer"></div>
				<input type=submit>
				<img src="assets/graphics/Frog_1.svg" style="grid-row: -3/span 2; grid-column: -3/span 2">
			</div>
		</form>
		{{end}}
	</body>
</html>

lesson.html代码与page_template_1_form.html代码相同,并且我在本地主机上运行整个程序。运行代码时没有显示任何错误,但它似乎仍然不起作用。我是不是遗漏了什么?


更多关于Golang中如何将模板保存到文件的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

乍一看,您似乎忘记在 lesson.html 文件中声明模板(例如 {{ define "lesson" }} ...模板内容... {{end}})。此外,我不太明白您为何要在运行时创建和加载另一个模板,不过您可以简单地使用 ParseGlob 来一步读取多个模板,这对于嵌套模板尤其有用。

更多关于Golang中如何将模板保存到文件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你忽略了某些错误,例如来自 os.Create("lesson.html") 的错误,下一行的 os.Open,以及之后的 io.Copy,还有 tmpl.Execute 等等。尝试记录这些错误,看看那里是否出了问题。

func main() {
    fmt.Println("hello world")
}

在Golang中将模板执行结果保存到文件时,你的代码存在几个关键问题。主要问题是你使用了os.O_APPEND模式打开文件,这会导致内容被追加到文件末尾而不是覆盖。以下是修正后的代码:

import (
    "html/template"
    "net/http"
    "os"
    "log"
)

type PageDetails struct {
    Content   string
    Submitted bool
}

func main() {
    // 解析模板文件
    tmpl, err := template.ParseFiles("page_template_1_form.html")
    if err != nil {
        log.Fatal("模板解析失败:", err)
    }
    
    var details PageDetails
    
    http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/"))))
    
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost {
            tmpl.Execute(w, nil)
            return
        }

        details = PageDetails{
            Content:   r.FormValue("content"),
            Submitted: true,
        }
        
        // 创建或截断文件(使用os.O_TRUNC覆盖内容)
        f, err := os.OpenFile("lesson.html", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
        if err != nil {
            log.Fatal("文件打开失败:", err)
        }
        defer f.Close()
        
        // 执行模板到文件
        err = tmpl.Execute(f, details)
        if err != nil {
            log.Print("模板执行错误: ", err)
        }
        
        // 同时输出到浏览器
        tmpl.Execute(w, details)
    })
    
    log.Fatal(http.ListenAndServe(":8080", nil))
}

关键修改点:

  1. 文件打开模式:使用os.O_TRUNC而不是os.O_APPEND,这样每次写入都会清空文件内容
  2. 简化流程:直接使用已解析的tmpl模板,无需重新解析lesson.html
  3. 文件权限:使用0644作为文件权限,这是更标准的文件权限设置
  4. 错误处理:添加了更详细的错误处理

如果你需要保留原始模板结构并生成新的HTML文件,这里是一个更清晰的版本:

func main() {
    // 解析模板
    tmpl := template.Must(template.ParseFiles("page_template_1_form.html"))
    
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost {
            tmpl.Execute(w, nil)
            return
        }
        
        // 创建页面数据
        details := PageDetails{
            Content:   r.FormValue("content"),
            Submitted: true,
        }
        
        // 生成HTML文件
        generateHTMLFile("lesson.html", tmpl, details)
        
        // 显示结果
        tmpl.Execute(w, details)
    })
    
    http.ListenAndServe(":8080", nil)
}

func generateHTMLFile(filename string, tmpl *template.Template, data PageDetails) error {
    // 创建文件(如果存在则覆盖)
    file, err := os.Create(filename)
    if err != nil {
        return err
    }
    defer file.Close()
    
    // 执行模板到文件
    return tmpl.Execute(file, data)
}

这样修改后,当用户提交表单时,模板会正确执行并将结果保存到lesson.html文件中,同时也会在浏览器中显示结果。

回到顶部