實現最簡單的模板替換

morya發表於2018-08-10

直接上程式碼

package main

import (
    "bytes"
    "fmt"
    "io"
    "strings"
)

type ParseState int

const (
    PS_TEXT ParseState = 1 + iota
    PS_FIELD
)

type StrMap map[string]string

func AppendField(out io.Writer, key string, fields StrMap) {
    if v, ok := fields[key]; ok {
        io.WriteString(out, v)
    }
}

func Render(tmpl string, fields StrMap) string {
    var out = &bytes.Buffer{}
    var field = &bytes.Buffer{}

    r := strings.NewReader(tmpl)

    var ps = PS_TEXT

    for {
        c, err := r.ReadByte()
        if err != nil {
            break
        }

        switch ps {
        case PS_TEXT:
            if c != '{' {
                out.WriteByte(c)
            } else {
                ps = PS_FIELD
            }

        case PS_FIELD:
            if c != '}' && ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
                field.WriteByte(c)
            } else {
                ps = PS_TEXT
                var key = field.String()
                AppendField(out, key, fields)
                field.Reset()
            }
        }
    }

    return out.String()
}

func main() {
    var tmpl = "name = {name} age={age} test empty={}  test bad {{ }}}"
    fields := make(StrMap)
    fields["name"] = "John"
    fields["age"] = "15"
    fmt.Println(Render(tmpl, fields))
    // result
    // name = John age=15 test empty=  test bad  }}}
}

相關文章