【问题标题】:Read file as template, execute it and write it back读取文件作为模板,执行并写回
【发布时间】:2015-12-09 16:30:44
【问题描述】:

我正在尝试解析可以注入在配置文件中定义的变量的 CSS 文件。目前该功能:

  1. 根据给定的路径参数打开文件
  2. 解析文件内容
  3. 通过注入配置变量来执行模板
  4. 将渲染的内容写入控制台而不是原始文件
func parse(path string) {
    f, err := ioutil.ReadFile(path)

    if err != nil {
        log.Print(err)
        return
    }

    // Parse requires a string
    t, err := template.New("css").Parse(string(f))

    if err != nil {
        log.Print(err)
        return
    }

    // A sample config
    config := map[string]string {
        "textColor": "#abcdef",
        "linkColorHover": "#ffaacc",
    }   

    // Execute needs some sort of io.Writer
    err = t.Execute(os.Stdout, config)  

    if err != nil {
        log.Print("Can't execute ", path)
    }
}

我的问题是 template.Parse() 需要内容作为字符串,template.Execute() 需要 io.Writer 作为参数。我试图用os.Open() 打开文件,它返回一个实现io.Writer 接口的文件对象。但是如何从这样的文件对象中获取文件的内容作为字符串以便与Parse() 一起使用?

【问题讨论】:

  • 我尝试扩展一个静态端生成器。因此我只需要这样做一次。

标签: file templates go io


【解决方案1】:

这是我用 Cerise Limón 的回答制作的函数

func createFileUsingTemplate(t *template.Template, filename string, data interface{}) error {
    f, err := os.Create(filename)
    if err != nil {
        return err
    }
    defer f.Close()

    err = t.Execute(f, data)
    if err != nil {
        return err
    }

    return nil
}

【讨论】:

    【解决方案2】:

    使用ParseFiles 解析模板。这段代码与问题中调用 ReadFile、template.New 和 Parse 的作用基本相同,但更短。

    t, err := template.ParseFiles(path)
    if err != nil {
        log.Print(err)
        return
    }
    

    使用os.Create打开输出文件。

    f, err := os.Create(path)
    if err != nil {
        log.Println("create file: ", err)
        return
    }
    

    一个文件是一个 io.Writer。可以直接对打开的文件执行模板:

    err = t.Execute(f, config)
    if err != nil {
        log.Print("execute: ", err)
        return
    }
    

    完成后关闭文件。

    f.Close()
    

    Complete working example on the playground.

    【讨论】:

    • 我使用 os.Walk("root", filterFunc) 和一个过滤器来查找所有 css 文件。如果脚本找到一个,它会使用路径调用parse()。那么,如果我只需要解析单个文件,调用ParseFiles() 是否有意义?最后:os.Create(path) 会覆盖原始文件,对吧?
    • 对于这种情况,您应该一次使用一个文件调用 ParseFiles。如答案中所述,使用单个文件校准 ParseFiles 可以保存代码。是的,这会覆盖原始文件。如果这不是您在问题中提出的问题,请澄清。
    • 不,这正是我所需要的。非常感谢。
    • 太好了,谢谢@CeriseLimón 我也需要这个。你能解释一下这是什么吗?以前从未见过map[string]string
    • @Sbe88 这是一个带有字符串键和字符串值的map
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-08
    • 2011-07-05
    • 1970-01-01
    • 2017-03-26
    • 2013-06-08
    相关资源
    最近更新 更多