🐷

Goのtemplateで改行を`<br>`にする

2022/10/20に公開

やってみました

背景

Goのテンプレートを使い、HTMLのテンプレートに文字列を埋め込んだりする場合、元の文字列が改行を含んでいるような場合はよくあると思います。
そのようなとき、そのままテンプレートに渡してしまうとHTMLは\nのような改行コードを改行と認識しませんので、どうにかして改行タグである<br>に変換してあげる必要があります。

実装

package main

import (
    "log"
    "os"
    "strings"
    "text/template"
)

const tpl = `<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <p>{{applyBrNewline (htmlEscape .)}}</p>
  </body>
</html>
`

const text = `1 < 100
は
「1 小なり 100」と
読みます。`

func main() {

    funcMap := template.FuncMap{
        "htmlEscape": func(in string) string {
            out := template.HTMLEscapeString(in)
            return out
        },
        "applyBrNewline": func(in string) string {
            out := strings.Replace(in, "\n", "<br>", -1)
            return out
        },
    }

    t, err := template.New("").Funcs(funcMap).Parse(tpl)
    if err != nil {
        log.Fatal(err)
    }

    if err := t.Execute(os.Stdout, text); err != nil {
        log.Fatal(err)
    }
}

結果

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <p>1 &lt; 100<br>は<br>「1 小なり 100」と<br>読みます。</p>
  </body>
</html>

元の文字列に含まれていた改行が<br>になり、ついでに<&lt;に変換されているのがわかると思います。

入力となる文字列を埋め込む前に、strings.Replacetemplate.HTMLEscapeStringを使ってよしなに加工してあげるのがキモとなります。
それぞれの処理はtemplate.FuncMapを使って呼び出すようにし、再利用性を少し高めてみました。

funcを入れ子にする場合には内側の結果をfuncごと()でくくってあげれば、内側のfuncの結果がそのまま外側のfuncに順次渡されるようです。

ではまた!

参考

Discussion