6

text/templateパッケージを使って簡単な作業をしようとしています。テンプレートの上部にあるサンプルは、私が使用しているものです。

'解析された'ファイルをtemplate.ParseFiles()適切に読み取って実行するようにするにはどうすればよいですか?

package main

import (
    "text/template"
    "os"
)

type Inventory struct {
    Material string
    Count    uint
}

func main() {
    sweaters := Inventory{"wool", 17}
    tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
    // tmpl, err := template.New("test").ParseFiles("file.txt")

    if err != nil { panic(err) }
    err = tmpl.Execute(os.Stdout, sweaters)
    if err != nil { panic(err) }
}

/*
Contents of file.txt:
{{.Count}} items are made of {{.Material}}

Error thrown:
panic: template: test:1: "test" is an incomplete or empty template

goroutine 1 [running]:
main.main()
    /tmp/templates/t.go:19 +0x21a

goroutine 2 [syscall]:
created by runtime.main
    /var/tmp/portage/dev-lang/go-1.0.1/work/go/src/pkg/runtime/proc.c:221
*/

私はこのコードのコピーをここのgolang遊び場に投稿しています

編集#1:私はこの問題についていくつかの調査を行ってきました...それExecute()は実際に例外をスローするメソッドであり、ParseFiles()一部ではないため、メソッド定義を確認しました:

// Execute applies a parsed template to the specified data object,
// and writes the output to wr.
func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
    defer errRecover(&err)
    value := reflect.ValueOf(data)
    state := &state{
        tmpl: t,
        wr:   wr,
        line: 1,
        vars: []variable{{"$", value}},
    }
    if t.Tree == nil || t.Root == nil {
        state.errorf("%q is an incomplete or empty template", t.name)
    }
    state.walk(value, t.Root)
    return
}

したがって、私は、インラインの「非ファイル」スタイルのt.Treeの値をダンプしました。tmplは次のとおりです。、で実行した場合、tmplは次のように&parse.Tree{Name:"test", Root:(*parse.ListNode)(0xf840030700), funcs:[]map[string]interface {}(nil), lex:(*parse.lexer)(nil), token:[2]parse.item{parse.item{typ:6, val:""}, parse.item{typ:9, val:"{{"}}, peekCount:1, vars:[]string(nil)}なりParseFiles()ます(*parse.Tree)(nil)。1つが間接参照であり、1つの値がポインターであるのは奇妙だと思います。これは謎を解くのに役立つかもしれません

4

2 に答える 2

18
sweaters := Inventory{"wool", 17}
tmpl, err := template.ParseFiles("file.txt")
if err != nil {
    panic(err)
}
err = tmpl.ExecuteTemplate(os.Stdout, "file.txt", sweaters)
if err != nil {
    panic(err)
}

多くのファイルがある場合は、ParseGlobを使用できます。

tmpl, err := template.ParseGlob("*.txt")
if err != nil {
    panic(err)
}
err = tmpl.ExecuteTemplate(os.Stdout, "file.txt", sweaters)
if err != nil {
    panic(err)
}
err = tmpl.ExecuteTemplate(os.Stdout, "file2.txt", sweaters)
if err != nil {
    panic(err)
}
于 2012-08-04T10:03:24.530 に答える
11

GoテンプレートparseFilesにはちょっとしたトリックがあります。

func parseFiles(t *Template, filenames ...string) (*Template, error) {
    if len(filenames) == 0 {
        // Not really a problem, but be consistent.
        return nil, fmt.Errorf("template: no files named in call to ParseFiles")
    }
    for _, filename := range filenames {
        b, err := ioutil.ReadFile(filename)
        if err != nil {
            return nil, err
        }
        s := string(b)
        name := filepath.Base(filename)
        // First template becomes return value if not already defined,
        // and we use that one for subsequent New calls to associate
        // all the templates together. Also, if this file has the same name
        // as t, this file becomes the contents of t, so
        //  t, err := New(name).Funcs(xxx).ParseFiles(name)
        // works. Otherwise we create a new template associated with t.
        var tmpl *Template
        if t == nil {
            t = New(name)
        }
        if name == t.Name() {
            tmpl = t
        } else {
            tmpl = t.New(name)
        }
        _, err = tmpl.Parse(s)
        if err != nil {
            return nil, err
        }
    }
    return t, nil
}

同じ名前のテンプレートのみが再利用されます。それ以外の場合は、新しいテンプレートを作成します。サンプルとして:

tmpl, err := template.New("test").ParseFiles("file.txt")

tmplは「test」という名前のテンプレートであり、「file.txt」という名前の別のテンプレートに関連付けられています。「test」テンプレートでExecuteを呼び出します。このテンプレートは空のテンプレートなので、「test is incompleteoremptytemplate」というエラーが発生します。

テンプレート名をfile.txtに変更すると機能しました

tmpl, err := template.New("file.txt").ParseFiles("file.txt")
于 2017-01-03T08:39:38.990 に答える