template

package
v1.26.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 15, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

templateパッケージは、テキスト出力を生成するためのデータ駆動型テンプレートを実装します。

HTML出力を生成するには、html/template を参照してください。 これはこのパッケージと同じインターフェースを持ち、 特定の攻撃に対して自動的にHTML出力を保護します。

テンプレートは、それをデータ構造に適用することで実行されます。テンプレート内の注釈は、 データ構造の要素(通常は構造体のフィールドやマップのキー)を参照して、実行を制御し、 表示する値を導き出します。テンプレートの実行は構造を歩き、カーソルを設定します。 これはピリオド '.' で表され、"dot"と呼ばれ、実行が進行するにつれて構造内の現在の位置の 値に設定されます。

このパッケージで採用されているセキュリティモデルは、テンプレートの作成者が信頼できることを前提としています。 このパッケージは出力の自動エスケープを行わないため、テンプレートにコードを注入すると、 テンプレートが信頼できないソースによって実行された場合、任意のコード実行につながる可能性があります。

テンプレートの入力テキストは、任意の形式のUTF-8エンコードされたテキストです。 「アクション」(データ評価や制御構造)は「{{」と「}}」で区切られ、 アクション外のすべてのテキストは変更されずに出力へコピーされます。

一度パースされると、テンプレートは並行して安全に実行することができますが、 並行実行がWriterを共有している場合、出力は交互になる可能性があります。

これは "17 items are made of wool" を出力する簡単な例です。

type Inventory struct {
	Material string
	Count    uint
}
sweaters := Inventory{"wool", 17}
tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
if err != nil { panic(err) }
err = tmpl.Execute(os.Stdout, sweaters)
if err != nil { panic(err) }

より複雑な例は以下に示されています。

テキストとスペース

デフォルトでは、アクション間のすべてのテキストは、テンプレートが実行されるときに そのままコピーされます。例えば、上記の例の " items are made of " という文字列は、 プログラムが実行されると標準出力に表示されます。

しかし、テンプレートのソースコードを整形するために、アクションの左 デリミタ(デフォルトでは "{{")が直後にマイナス記号と空白に続いている場合、 直前のテキストからすべての末尾の空白がトリムされます。 同様に、右デリミタ("}}")が空白とマイナス記号に先行されている場合、 直後のテキストからすべての先頭の空白がトリムされます。 これらのトリムマーカーでは、空白が存在しなければなりません: "{{- 3}}"は"{{3}}"と同じですが、直前のテキストをトリムします、一方 "{{-3}}"は数値-3を含むアクションとして解析されます。

例えば、ソースが以下のテンプレートを実行すると、

"{{23 -}} < {{- 45}}"

生成される出力は以下のようになります。

"23<45"

このトリミングにおいて、空白文字の定義はGoと同じです:スペース、水平タブ、キャリッジリターン、改行。

アクション

以下にアクションのリストを示します。"引数"と"パイプライン"は、 データの評価であり、それぞれに続く対応するセクションで詳細に定義されています。

{{/* コメント */}}
{{- /* 前後のテキストから空白をトリムしたコメント */ -}}
	コメント; 破棄されます。改行を含むことができます。
	コメントはネストできず、ここに示されているように
	デリミタで始まり終わらなければなりません。

{{パイプライン}}
	パイプラインの値のデフォルトのテキスト表現(fmt.Printによって
	印刷されるのと同じ)が出力にコピーされます。

{{if パイプライン}} T1 {{end}}
	パイプラインの値が空の場合、出力は生成されません。
	それ以外の場合、T1が実行されます。空の値はfalse、0、
	任意のnilポインタまたはインターフェース値、および長さゼロの
	任意の配列、スライス、マップ、または文字列です。
	ドットは影響を受けません。

{{if パイプライン}} T1 {{else}} T0 {{end}}
	パイプラインの値が空の場合、T0が実行されます。
	それ以外の場合、T1が実行されます。ドットは影響を受けません。

{{if パイプライン}} T1 {{else if パイプライン}} T0 {{end}}
	if-elseチェーンの見た目を簡素化するために、ifのelseアクションは
	直接別のifを含むことができます。その効果は、以下を書くのと全く同じです。
		{{if パイプライン}} T1 {{else}}{{if パイプライン}} T0 {{end}}{{end}}

{{range pipeline}} T1 {{end}}
		パイプラインの値は配列、スライス、マップ、iter.Seq、iter.Seq2、整数またはチャネルでなければなりません。
		パイプラインの値の長さがゼロの場合は何も出力されません。
		それ以外の場合、ドットは配列、スライス、またはマップの各要素に順次設定され、T1が実行されます。
		値がマップで、キーが基本型かつ順序が定義されている場合、要素はキー順に訪問されます。

{{range pipeline}} T1 {{else}} T0 {{end}}
		パイプラインの値は配列、スライス、マップ、iter.Seq、iter.Seq2、整数またはチャネルでなければなりません。
		パイプラインの値の長さがゼロの場合、ドットは変更されずT0が実行されます。
		それ以外の場合、ドットは配列、スライス、またはマップの各要素に順次設定され、T1が実行されます。

{{break}}
	最も内側の {{range pipeline}} ループが早期に終了し、
	現在の反復を停止し、残りのすべての反復をバイパスします。

{{continue}}
	最も内側の {{range pipeline}} ループの現在の反復が停止し、
	ループは次の反復を開始します。

{{template "name"}}
	指定された名前のテンプレートがnilデータで実行されます。

{{template "name" パイプライン}}
	指定された名前のテンプレートが実行され、ドットはパイプラインの値に設定されます。

{{block "name" pipeline}} T1 {{end}}
	ブロックは、テンプレートを定義するための省略形です
		{{define "name"}} T1 {{end}}
	そして、それをその場で実行します
		{{template "name" pipeline}}
	典型的な使用法は、一連のルートテンプレートを定義し、
	それらをブロックテンプレートを再定義することでカスタマイズすることです。

{{with パイプライン}} T1 {{end}}
	パイプラインの値が空の場合、出力は生成されません。
	それ以外の場合、ドットはパイプラインの値に設定され、T1が実行されます。

{{with パイプライン}} T1 {{else}} T0 {{end}}
	パイプラインの値が空の場合、ドットは影響を受けず、T0が実行されます。
	それ以外の場合、ドットはパイプラインの値に設定され、T1が実行されます。

{{with pipeline}} T1 {{else with pipeline}} T0 {{end}}
	with-elseチェーンの見た目を簡単にするために、withのelseアクションは
	直接別のwithを含めることができます。その効果は、以下のように書くのと
	全く同じです。
		{{with pipeline}} T1 {{else}}{{with pipeline}} T0 {{end}}{{end}}

Arguments

引数は、以下のいずれかによって示される単純な値です。

  • Go構文のブール値、文字列、文字、整数、浮動小数点数、虚数または複素数定数。 これらはGoの無名定数のように振る舞います。Goと同様に、大きな整数定数が 割り当てられたときや関数に渡されたときにオーバーフローするかどうかは、 ホストマシンのintが32ビットか64ビットかに依存する場合があります。
  • Goの無名nilを表すキーワードnil。
  • 文字 '.'(ピリオド): . 結果はdotの値です。
  • 変数名。これはドル記号で始まる英数字の文字列(空である可能性もあります)です。 例えば $piOver2 または $ 結果は変数の値です。変数については後述します。
  • データのフィールド名。これは構造体でなければならず、ピリオドで始まります。 例えば .Field 結果はフィールドの値です。フィールドの呼び出しは連鎖できます: .Field1.Field2 フィールドは変数上でも評価でき、連鎖も可能です: $x.Field1.Field2
  • データのキー名。これはマップでなければならず、ピリオドで始まります。 例えば .Key 結果はキーでインデックスされたマップ要素の値です。 キーの呼び出しは連鎖でき、フィールドと任意の深さで組み合わせることができます: .Field1.Key1.Field2.Key2 キーは英数字の識別子でなければなりませんが、フィールド名とは異なり、 大文字で始まる必要はありません。キーは変数上でも評価でき、連鎖も可能です: $x.key1.key2
  • データのniladicメソッド名。これはピリオドで始まります。 例えば .Method 結果はメソッドをレシーバとして呼び出した値、dot.Method()です。 このようなメソッドは1つの戻り値(任意の型)または2つの戻り値を持ち、 2つ目の戻り値がエラーである必要があります。2つの戻り値があり、 戻り値のエラーがnilでない場合、実行は終了し、エラーがExecuteの値として 呼び出し元に返されます。メソッドの呼び出しは連鎖でき、フィールドやキーと 任意の深さで組み合わせることができます: .Field1.Key1.Method1.Field2.Key2.Method2 メソッドは変数上でも評価でき、連鎖も可能です: $x.Method1.Field
  • niladic関数の名前。例えば fun 結果は関数を呼び出した値、fun()です。戻り値の型と値はメソッドと同様に振る舞います。 関数と関数名については後述します。
  • 上記のいずれかの括弧で囲まれたインスタンス。結果はフィールドまたはマップキーの 呼び出しによってアクセスできます。 print (.F1 arg1) (.F2 arg2) (.StructValuedMethod "arg").Field

引数は任意の型に評価される可能性があります。ポインタである場合、 実装は必要に応じて自動的に基底型に間接参照します。 評価が関数値を生成する場合(例えば、構造体の関数値フィールド)、 関数は自動的に呼び出されませんが、ifアクションなどの真偽値として使用できます。 呼び出すには、以下で定義されているcall関数を使用します。 パイプライン パイプラインは「コマンド」の連鎖されたシーケンスである可能性があります。 コマンドは単純な値(引数)または関数やメソッドの呼び出しであり、 複数の引数を持つこともあります:

Argument
	結果は引数の評価値です。
.Method [Argument...]
	メソッドは単独であるか、チェーンの最後の要素であることができますが、
	チェーンの中間にあるメソッドとは異なり、引数を取ることができます。
	結果は、引数を用いてメソッドを呼び出した値です:
		dot.Method(Argument1, etc.)
functionName [Argument...]
	結果は、名前に関連付けられた関数を呼び出した値です:
		function(Argument1, etc.)
	関数と関数名については以下で説明します。

パイプラインは、パイプライン文字 '|' でコマンドのシーケンスを区切ることにより "チェーン化"することができます。チェーン化されたパイプラインでは、各コマンドの結果が 次のコマンドの最後の引数として渡されます。パイプラインの最終コマンドの出力が パイプラインの値となります。

コマンドの出力は、値が1つまたは2つ(2つ目の型はerror)のいずれかになります。 もし2つ目の値が存在し、非nilと評価される場合、実行は終了し、そのエラーは Executeの呼び出し元に返されます。

変数

アクション内のパイプラインは、結果をキャプチャするために変数を初期化することができます。 初期化は以下の構文を持ちます

$変数 := パイプライン

ここで、$変数は変数の名前です。変数を宣言するアクションは出力を生成しません。

以前に宣言された変数は、以下の構文を使用して割り当てることもできます

$変数 = パイプライン

"range"アクションが変数を初期化する場合、変数は反復の連続する要素に設定されます。 また、"range"は、カンマで区切られた2つの変数を宣言することもできます:

range $index, $element := パイプライン

この場合、$indexと$elementは、配列/スライスのインデックスまたはマップキーと要素の 連続する値に設定されます。ただし、変数が1つだけの場合、要素が割り当てられます。 これはGoのrange節の慣習とは逆です。

変数のスコープは、それが宣言された制御構造("if"、"with"、または"range")の "end"アクションまで、またはそのような制御構造がない場合はテンプレートの終わりまで 広がります。テンプレートの呼び出しは、その呼び出し地点から変数を継承しません。

実行が開始されると、$はExecuteに渡されたデータ引数、つまり、dotの開始値に設定されます。

以下は、パイプラインと変数を示す一行のテンプレートの例です。 すべてが引用符で囲まれた単語 "output" を生成します:

{{"\"output\""}}
	A string constant.
{{`"output"`}}
	A raw string constant.
{{printf "%q" "output"}}
	A function call.
{{"output" | printf "%q"}}
	A function call whose final argument comes from the previous
	command.
{{printf "%q" (print "out" "put")}}
	A parenthesized argument.
{{"put" | printf "%s%s" "out" | printf "%q"}}
	A more elaborate call.
{{"output" | printf "%s" | printf "%q"}}
	A longer chain.
{{with "output"}}{{printf "%q" .}}{{end}}
	A with action using dot.
{{with $x := "output" | printf "%q"}}{{$x}}{{end}}
	A with action that creates and uses a variable.
{{with $x := "output"}}{{printf "%q" $x}}{{end}}
	A with action that uses the variable in another action.
{{with $x := "output"}}{{$x | printf "%q"}}{{end}}
	The same, but pipelined.

関数

実行中、関数は2つの関数マップで見つけられます:まずテンプレート内、次にグローバル関数マップ内です。 デフォルトでは、テンプレート内には関数は定義されていませんが、Funcsメソッドを使用して追加することができます。

事前定義されたグローバル関数は以下のように名付けられます。

and
	引数のブール型のANDを返します。つまり、最初の空の引数または最後の引数を返します。
	つまり、"and x y"は"if x then y else x"と同じように動作します。
	評価は引数を左から右へと進み、結果が決定した時点で返ります。
call
	最初の引数(関数である必要があります)を、残りの引数をパラメータとして呼び出した結果を返します。
	したがって、"call .X.Y 1 2"はGoの表記ではdot.X.Y(1, 2)となります。ここで
	Yは関数値フィールド、マップエントリ、またはそれに類するものです。
	最初の引数は、関数型の値を生成する評価の結果でなければなりません
	(printのような事前定義された関数とは異なります)。関数は
	1つまたは2つの結果値を返す必要があり、2つ目の型はerrorです。引数が関数と一致しない場合や
	返されたエラー値が非nilの場合、実行は停止します。
html
	引数のテキスト表現のエスケープされたHTML相当を返します。この関数は
	html/templateでは利用できません、いくつかの例外を除いて。
index
	最初の引数を次の引数でインデックス化した結果を返します。
	したがって、"index x 1 2 3"はGoの構文ではx[1][2][3]となります。
	各インデックス化されたアイテムは、マップ、スライス、または配列でなければなりません。
slice
	sliceは、最初の引数を残りの引数でスライスした結果を返します。
	したがって、"slice x 1 2"はGoの構文ではx[1:2]、"slice x"はx[:]、
	"slice x 1"はx[1:]、そして"slice x 1 2 3"はx[1:2:3]となります。
	最初の引数は、文字列、スライス、または配列でなければなりません。
js
	引数のテキスト表現のエスケープされたJavaScript相当を返します。
len
	引数の整数長を返します。
not
	単一の引数のブール否定を返します。
or
	引数のブール型のORを返します。つまり、最初の非空の引数または最後の引数を返します。
	したがって、"or x y"は"if x then x else y"と同じように動作します。
	評価は引数を左から右へと進み、結果が決定した時点で返ります。
print
	fmt.Sprintのエイリアス
printf
	fmt.Sprintfのエイリアス
println
	fmt.Sprintlnのエイリアス
urlquery
	その引数のテキスト表現のエスケープされた値を、URLクエリに埋め込むのに適した形で返します。
	この関数はhtml/templateでは利用できません、いくつかの例外を除いて。

ブール関数は、ゼロ値をfalse、非ゼロ値をtrueとして取ります。

また、関数として定義された一連の二項比較演算子もあります:

eq
	arg1 == arg2のブール型の真偽値を返します
ne
	arg1 != arg2のブール型の真偽値を返します
lt
	arg1 < arg2のブール型の真偽値を返します
le
	arg1 <= arg2のブール型の真偽値を返します
gt
	arg1 > arg2のブール型の真偽値を返します
ge
	arg1 >= arg2のブール型の真偽値を返します

よりシンプルな多方向の等価性テストのために、eq(のみ)は2つ以上の 引数を受け入れ、2番目以降を最初のものと比較し、実質的に以下を返します

arg1==arg2 || arg1==arg3 || arg1==arg4 ...

(ただし、Goの||とは異なり、eqは関数呼び出しであり、すべての 引数が評価されます。)

比較関数は、Goが比較可能と定義している任意の型の値で動作します。 基本的な型、例えば整数については、ルールが緩和されています: サイズと正確な型は無視され、任意の整数値、符号付きまたは符号なし、 は他の任意の整数値と比較することができます。(算術値が比較され、 ビットパターンではないので、すべての負の整数はすべての符号なし整数より小さいです。) しかし、通常通り、intをfloat32などと比較することはできません。

関連付けられたテンプレート

各テンプレートは、作成時に指定された文字列によって名付けられます。また、各 テンプレートは、名前で呼び出すことができる他のテンプレートとゼロ以上関連付けられています。 そのような関連付けは推移的であり、テンプレートの名前空間を形成します。

テンプレートは、テンプレート呼び出しを使用して、別の関連付けられた テンプレートをインスタンス化することができます。上記の "template" アクションの説明を参照してください。 名前は、呼び出しを含むテンプレートに関連付けられたテンプレートの名前でなければなりません。

ネストしたテンプレート定義

テンプレートを解析するとき、別のテンプレートが定義され、解析中の テンプレートと関連付けられることがあります。テンプレート定義は、 Goプログラムのグローバル変数のように、テンプレートのトップレベルに 現れなければなりません。

そのような定義の構文は、各テンプレート宣言を "define"と"end"アクションで囲むことです。

"define"アクションは、文字列定数を提供することで作成されるテンプレートの名前を指定します。 以下に簡単な例を示します:

{{define "T1"}}ONE{{end}}
{{define "T2"}}TWO{{end}}
{{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
{{template "T3"}}

これは、T1とT2という2つのテンプレートを定義し、実行時に他の2つを呼び出す T3という3つ目のテンプレートを定義します。最後にT3を呼び出します。このテンプレートが 実行されると、以下のテキストが生成されます

ONE TWO

構造上、テンプレートは一つの関連付けのみに存在することができます。もしテンプレートを 複数の関連付けからアドレス可能にする必要がある場合、テンプレート定義は複数回パースされて 異なる*Template値を作成するか、Template.Clone または Template.AddParseTree メソッドでコピーされなければなりません。

Parseは、関連する複数のテンプレートを組み立てるために複数回呼び出すことができます。 関連するテンプレートがファイルに保存されている場合のパースを簡単に行うための ParseFilesParseGlobTemplate.ParseFiles および Template.ParseGlob を参照してください。

テンプレートは直接実行するか、または名前で識別される関連付けられたテンプレートを実行する ExecuteTemplateを通じて実行することができます。上記の例を呼び出すために、私たちは 以下のように書くかもしれません。

err := tmpl.Execute(os.Stdout, "no data needed")
if err != nil {
	log.Fatalf("execution failed: %s", err)
}

or to invoke a particular template explicitly by name,

err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed")
if err != nil {
	log.Fatalf("execution failed: %s", err)
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func HTMLEscape

func HTMLEscape(w io.Writer, b []byte)

HTMLEscapeは、プレーンテキストデータbのエスケープされたHTML相当をwに書き込みます。

func HTMLEscapeString

func HTMLEscapeString(s string) string

HTMLEscapeStringは、プレーンテキストデータsのエスケープされたHTML相当を返します。

func HTMLEscaper

func HTMLEscaper(args ...any) string

HTMLEscaperは、その引数のテキスト表現のエスケープされたHTML相当を返します。

func IsTrue added in v1.6.0

func IsTrue(val any) (truth, ok bool)

IsTrueは、値がその型のゼロでない「真」であるか、 および値が意味のある真理値を持っているかどうかを報告します。 これはifやその他のそのようなアクションで使用される真理の定義です。

func JSEscape

func JSEscape(w io.Writer, b []byte)

JSEscapeは、プレーンテキストデータbのエスケープされたJavaScript相当をwに書き込みます。

func JSEscapeString

func JSEscapeString(s string) string

JSEscapeStringは、プレーンテキストデータsのエスケープされたJavaScript相当を返します。

func JSEscaper

func JSEscaper(args ...any) string

JSEscaperは、その引数のテキスト表現のエスケープされたJavaScript相当を返します。

func URLQueryEscaper

func URLQueryEscaper(args ...any) string

URLQueryEscaperは、URLクエリに埋め込む形式に適した、その引数のテキスト表現のエスケープされた値を返します。

Types

type ExecError added in v1.6.0

type ExecError struct {
	Name string
	Err  error
}

ExecErrorは、Executeがテンプレートを評価する際にエラーが発生したときに返される カスタムエラータイプです。(書き込みエラーが発生した場合、実際のエラーが返されます。 それはExecErrorタイプではありません。)

func (ExecError) Error added in v1.6.0

func (e ExecError) Error() string

func (ExecError) Unwrap added in v1.13.0

func (e ExecError) Unwrap() error

type FuncMap

type FuncMap map[string]any

FuncMapは、名前から関数へのマッピングを定義するマップの型です。 各関数は、単一の戻り値を持つか、または二つの戻り値を持つ必要があり、 その二つ目の型はエラーです。その場合、もし二つ目の(エラー)戻り値が実行中に非nilに評価された場合、 実行は終了し、Executeはそのエラーを返します。

Executeが返すエラーは元のエラーをラップしています。アンラップするには errors.AsType を呼び出してください。

テンプレートの実行が引数リストを持つ関数を呼び出すとき、そのリストは 関数のパラメータタイプに割り当て可能でなければなりません。任意のタイプの引数に適用することを意図した 関数は、interface{}型または reflect.Value 型のパラメータを使用できます。同様に、任意の タイプの結果を返すことを意図した関数は、interface{}または reflect.Value を返すことができます。

type Template

type Template struct {
	*parse.Tree
	// contains filtered or unexported fields
}

Templateは、解析されたテンプレートの表現です。*parse.Tree フィールドは、html/template による使用のためだけにエクスポートされており、 他のすべてのクライアントによって未エクスポートとして扱われるべきです。

Example
package main

import (
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/os"
	"github.com/shogo82148/std/text/template"
)

func main() {
	// Define a template.
	const letter = `
Dear {{.Name}},
{{if .Attended}}
It was a pleasure to see you at the wedding.
{{- else}}
It is a shame you couldn't make it to the wedding.
{{- end}}
{{with .Gift -}}
Thank you for the lovely {{.}}.
{{end}}
Best wishes,
Josie
`

	// テンプレートに挿入するためのデータを準備します。
	type Recipient struct {
		Name, Gift string
		Attended   bool
	}
	var recipients = []Recipient{
		{"Aunt Mildred", "bone china tea set", true},
		{"Uncle John", "moleskin pants", false},
		{"Cousin Rodney", "", false},
	}

	// 新しいテンプレートを作成し、その中にレターを解析します。
	t := template.Must(template.New("letter").Parse(letter))

	// 各受信者に対してテンプレートを実行します。
	for _, r := range recipients {
		err := t.Execute(os.Stdout, r)
		if err != nil {
			log.Println("executing template:", err)
		}
	}

}
Output:
Dear Aunt Mildred,

It was a pleasure to see you at the wedding.
Thank you for the lovely bone china tea set.

Best wishes,
Josie

Dear Uncle John,

It is a shame you couldn't make it to the wedding.
Thank you for the lovely moleskin pants.

Best wishes,
Josie

Dear Cousin Rodney,

It is a shame you couldn't make it to the wedding.

Best wishes,
Josie
Example (Block)
package main

import (
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/os"
	"github.com/shogo82148/std/strings"
	"github.com/shogo82148/std/text/template"
)

func main() {
	const (
		master  = `Names:{{block "list" .}}{{"\n"}}{{range .}}{{println "-" .}}{{end}}{{end}}`
		overlay = `{{define "list"}} {{join . ", "}}{{end}} `
	)
	var (
		funcs     = template.FuncMap{"join": strings.Join}
		guardians = []string{"Gamora", "Groot", "Nebula", "Rocket", "Star-Lord"}
	)
	masterTmpl, err := template.New("master").Funcs(funcs).Parse(master)
	if err != nil {
		log.Fatal(err)
	}
	overlayTmpl, err := template.Must(masterTmpl.Clone()).Parse(overlay)
	if err != nil {
		log.Fatal(err)
	}
	if err := masterTmpl.Execute(os.Stdout, guardians); err != nil {
		log.Fatal(err)
	}
	if err := overlayTmpl.Execute(os.Stdout, guardians); err != nil {
		log.Fatal(err)
	}
}
Output:
Names:
- Gamora
- Groot
- Nebula
- Rocket
- Star-Lord
Names: Gamora, Groot, Nebula, Rocket, Star-Lord
Example (Func)

This example demonstrates a custom function to process template text. It installs the strings.Title function and uses it to Make Title Text Look Good In Our Template's Output.

package main

import (
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/os"
	"github.com/shogo82148/std/strings"
	"github.com/shogo82148/std/text/template"
)

func main() {
	// 最初に、関数を登録するためのFuncMapを作成します。
	funcMap := template.FuncMap{
		// 名前 "title" は、テンプレートテキスト内で関数が呼ばれる名前です。
		"title": strings.Title,
	}

	// 関数をテストするためのシンプルなテンプレート定義。
	// 入力テキストをいくつかの方法で出力します:
	// - オリジナル
	// - タイトルケース
	// - タイトルケースにした後に %q で出力
	// - %q で出力した後にタイトルケースにします。
	const templateText = `
Input: {{printf "%q" .}}
Output 0: {{title .}}
Output 1: {{title . | printf "%q"}}
Output 2: {{printf "%q" . | title}}
`

	// テンプレートを作成し、関数マップを追加し、テキストを解析します。
	tmpl, err := template.New("titleTest").Funcs(funcMap).Parse(templateText)
	if err != nil {
		log.Fatalf("parsing: %s", err)
	}

	// テンプレートを実行して出力を確認します。
	err = tmpl.Execute(os.Stdout, "the go programming language")
	if err != nil {
		log.Fatalf("execution: %s", err)
	}

}
Output:
Input: "the go programming language"
Output 0: The Go Programming Language
Output 1: "The Go Programming Language"
Output 2: "The Go Programming Language"
Example (Funcs)

This example demonstrates registering two custom template functions and how to overwite one of the functions after the template has been parsed. Overwriting can be used, for example, to alter the operation of cloned templates.

package main

import (
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/os"
	"github.com/shogo82148/std/strings"
	"github.com/shogo82148/std/text/template"
)

func main() {

	// Define a simple template to test the functions.
	const tmpl = `{{ . | lower | repeat }}`

	// Define the template funcMap with two functions.
	var funcMap = template.FuncMap{
		"lower":  strings.ToLower,
		"repeat": func(s string) string { return strings.Repeat(s, 2) },
	}

	// Define a New template, add the funcMap using Funcs and then Parse
	// the template.
	parsedTmpl, err := template.New("t").Funcs(funcMap).Parse(tmpl)
	if err != nil {
		log.Fatal(err)
	}
	if err := parsedTmpl.Execute(os.Stdout, "ABC\n"); err != nil {
		log.Fatal(err)
	}

	// [Funcs] must be called before a template is parsed to add
	// functions to the template. [Funcs] can also be used after a
	// template is parsed to overwrite template functions.
	//
	// Here the function identified by "repeat" is overwritten.
	parsedTmpl.Funcs(template.FuncMap{
		"repeat": func(s string) string { return strings.Repeat(s, 3) },
	})
	if err := parsedTmpl.Execute(os.Stdout, "DEF\n"); err != nil {
		log.Fatal(err)
	}
}
Output:
abc
abc
def
def
def
Example (Glob)

ここでは、ディレクトリから一連のテンプレートをロードする方法を示します。

// ここでは、一時的なディレクトリを作成し、それをサンプルの
// テンプレート定義ファイルで満たします。通常、テンプレートファイルはすでに
// プログラムが知っている何らかの場所に存在します。
dir := createTestDir([]templateFile{
	// T0.tmplは、単にT1を呼び出すプレーンなテンプレートファイルです。
	{"T0.tmpl", `T0 invokes T1: ({{template "T1"}})`},
	// T1.tmplは、T2を呼び出すテンプレート、T1を定義します。
	{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
	// T2.tmplは、テンプレートT2を定義します。
	{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
})
// テスト後のクリーンアップ;これも例として実行する際の特性です。
defer os.RemoveAll(dir)

// patternは、すべてのテンプレートファイルを見つけるために使用されるglobパターンです。
pattern := filepath.Join(dir, "*.tmpl")

// ここからが実際の例です。
// T0.tmplは最初にマッチした名前なので、それが開始テンプレートとなり、
// ParseGlobによって返される値となります。
tmpl := template.Must(template.ParseGlob(pattern))

err := tmpl.Execute(os.Stdout, nil)
if err != nil {
	log.Fatalf("template execution: %s", err)
}
Output:
T0 invokes T1: (T1 invokes T2: (This is T2))
Example (Helpers)

この例は、いくつかのテンプレートを共有し、それらを異なるコンテキストで 使用する一つの方法を示しています。このバリアントでは、既存のテンプレートの バンドルに手動で複数のドライバーテンプレートを追加します。

// ここでは、一時的なディレクトリを作成し、それをサンプルの
// テンプレート定義ファイルで満たします。通常、テンプレートファイルはすでに
// プログラムが知っている何らかの場所に存在します。
dir := createTestDir([]templateFile{
	// T1.tmplは、T2を呼び出すテンプレート、T1を定義します。
	{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
	// T2.tmplは、テンプレートT2を定義します。
	{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
})
// テスト後のクリーンアップ;これも例として実行する際の特性です。
defer os.RemoveAll(dir)

// patternは、すべてのテンプレートファイルを見つけるために使用されるglobパターンです。
pattern := filepath.Join(dir, "*.tmpl")

// ここからが実際の例です。
// ヘルパーをロードします。
templates := template.Must(template.ParseGlob(pattern))
// 明示的なテンプレート定義を使用して、一連のテンプレートに一つのドライバーテンプレートを追加します。
_, err := templates.Parse("{{define `driver1`}}Driver 1 calls T1: ({{template `T1`}})\n{{end}}")
if err != nil {
	log.Fatal("parsing driver1: ", err)
}
// 別のドライバーテンプレートを追加します。
_, err = templates.Parse("{{define `driver2`}}Driver 2 calls T2: ({{template `T2`}})\n{{end}}")
if err != nil {
	log.Fatal("parsing driver2: ", err)
}
// 実行前にすべてのテンプレートをロードします。このパッケージはそのような振る舞いを
// 必要としませんが、html/templateのエスケープ処理はそれを必要とするので、それは良い習慣です。
err = templates.ExecuteTemplate(os.Stdout, "driver1", nil)
if err != nil {
	log.Fatalf("driver1 execution: %s", err)
}
err = templates.ExecuteTemplate(os.Stdout, "driver2", nil)
if err != nil {
	log.Fatalf("driver2 execution: %s", err)
}
Output:
Driver 1 calls T1: (T1 invokes T2: (This is T2))
Driver 2 calls T2: (This is T2)
Example (If)

This example demonstrates how to use "if".

package main

import (
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/os"
	"github.com/shogo82148/std/text/template"
)

func main() {
	type book struct {
		Stars float32
		Name  string
	}

	tpl, err := template.New("book").Parse(`{{ if (gt .Stars 4.0) }}"{{.Name }}" is a great book.{{ else }}"{{.Name}}" is not a great book.{{ end }}`)
	if err != nil {
		log.Fatalf("failed to parse template: %s", err)
	}

	b := &book{
		Stars: 4.9,
		Name:  "Good Night, Gopher",
	}
	err = tpl.Execute(os.Stdout, b)
	if err != nil {
		log.Fatalf("failed to execute template: %s", err)
	}

}
Output:
"Good Night, Gopher" is a great book.
Example (Share)

この例は、一つのグループのドライバーテンプレートを、異なるセットのヘルパーテンプレートと どのように使用するかを示しています。

// ここでは、一時的なディレクトリを作成し、それをサンプルの
// テンプレート定義ファイルで満たします。通常、テンプレートファイルはすでに
// プログラムが知っている何らかの場所に存在します。
dir := createTestDir([]templateFile{
	// T0.tmplは、単にT1を呼び出すプレーンなテンプレートファイルです。
	{"T0.tmpl", "T0 ({{.}} version) invokes T1: ({{template `T1`}})\n"},
	// T1.tmplは、T2を呼び出すテンプレート、T1を定義します。注意:T2は定義されていません
	{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
})
// テスト後のクリーンアップ;これも例として実行する際の特性です。
defer os.RemoveAll(dir)

// patternは、すべてのテンプレートファイルを見つけるために使用されるglobパターンです。
pattern := filepath.Join(dir, "*.tmpl")

// ここからが実際の例です。
// ドライバーをロードします。
drivers := template.Must(template.ParseGlob(pattern))

// 我々はT2テンプレートの実装を定義しなければなりません。まず、
// ドライバーをクローンし、その後、テンプレート名前空間にT2の定義を追加します。

// 1. ヘルパーセットをクローンして、それらを実行するための新しい名前空間を作成します。
first, err := drivers.Clone()
if err != nil {
	log.Fatal("cloning helpers: ", err)
}
// 2. T2、バージョンAを定義し、解析します。
_, err = first.Parse("{{define `T2`}}T2, version A{{end}}")
if err != nil {
	log.Fatal("parsing T2: ", err)
}

// 今度は全体を繰り返しますが、T2の別のバージョンを使用します。
// 1. ドライバーをクローンします。
second, err := drivers.Clone()
if err != nil {
	log.Fatal("cloning drivers: ", err)
}
// 2. T2、バージョンBを定義し、解析します。
_, err = second.Parse("{{define `T2`}}T2, version B{{end}}")
if err != nil {
	log.Fatal("parsing T2: ", err)
}

// テンプレートを逆の順序で実行して、
// 最初のものが二番目のものに影響を受けないことを確認します。
err = second.ExecuteTemplate(os.Stdout, "T0.tmpl", "second")
if err != nil {
	log.Fatalf("second execution: %s", err)
}
err = first.ExecuteTemplate(os.Stdout, "T0.tmpl", "first")
if err != nil {
	log.Fatalf("first: execution: %s", err)
}
Output:
T0 (second version) invokes T1: (T1 invokes T2: (T2, version B))
T0 (first version) invokes T1: (T1 invokes T2: (T2, version A))

func Must

func Must(t *Template, err error) *Template

Mustは、(*Template, error)を返す関数への呼び出しをラップし、 エラーが非nilの場合にパニックを起こすヘルパーです。これは変数の 初期化などで使用することを意図しています。

var t = template.Must(template.New("name").Parse("text"))

func New

func New(name string) *Template

Newは、指定された名前を持つ新しい未定義のテンプレートを割り当てます。

func ParseFS added in v1.16.0

func ParseFS(fsys fs.FS, patterns ...string) (*Template, error)

ParseFSは、Template.ParseFilesTemplate.ParseGlob と似ていますが、ホストオペレーティングシステムの ファイルシステムの代わりにファイルシステムfsysから読み取ります。 それはグロブパターンのリストを受け入れます(path.Match を参照)。 (ほとんどのファイル名は、自分自身のみにマッチするグロブパターンとして機能します。)

func ParseFiles

func ParseFiles(filenames ...string) (*Template, error)

ParseFilesは新しい Template を作成し、指定されたファイルからテンプレート定義を解析します。 返されるテンプレートの名前は、最初のファイルのベース名と解析された内容を持つことになります。 ファイルは少なくとも1つ必要です。 エラーが発生した場合、解析は停止し、返される*Templateはnilになります。

異なるディレクトリにある同名の複数のファイルを解析するとき、 最後に指定されたものが結果となります。 例えば、ParseFiles("a/foo", "b/foo")は "b/foo" を "foo" という名前のテンプレートとして保存し、 "a/foo" は利用できません。

func ParseGlob

func ParseGlob(pattern string) (*Template, error)

ParseGlobは新しい Template を作成し、パターンによって識別された ファイルからテンプレート定義を解析します。ファイルは [filepath.Match] の セマンティクスに従ってマッチし、パターンは少なくとも1つのファイルと マッチしなければなりません。返されるテンプレートは、パターンによって マッチした最初のファイルの [filepath.Base] 名と(解析された)内容を持つことになります。 ParseGlobは、パターンによってマッチしたファイルのリストで ParseFiles を 呼び出すのと同等です。

異なるディレクトリにある同名の複数のファイルを解析するとき、 最後に指定されたものが結果となります。

func (*Template) AddParseTree

func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error)

AddParseTreeは、引数のパースツリーをテンプレートtに関連付け、 それに指定された名前を付けます。テンプレートがまだ定義されていない場合、 このツリーがその定義となります。すでに定義されていてその名前を持っている場合、 既存の定義が置き換えられます。それ以外の場合は、新しいテンプレートが作成され、 定義され、返されます。

func (*Template) Clone

func (t *Template) Clone() (*Template, error)

Cloneは、関連付けられたすべてのテンプレートを含むテンプレートの複製を返します。 実際の表現はコピーされませんが、関連付けられたテンプレートの名前空間はコピーされるため、 コピーでのさらなる Template.Parse の呼び出しは、コピーにテンプレートを追加しますが、元のテンプレートには追加しません。 Cloneは、共通のテンプレートを準備し、それらを他のテンプレートのバリアント定義とともに使用するために、 クローン作成後にバリアントを追加することで使用できます。

func (*Template) DefinedTemplates added in v1.5.0

func (t *Template) DefinedTemplates() string

DefinedTemplatesは、定義されたテンプレートのリストを文字列として返します。 これは文字列 "; defined templates are: " で始まります。もし定義されたテンプレートがなければ、 空の文字列を返します。ここと html/template でエラーメッセージを生成するために使用されます。

func (*Template) Delims

func (t *Template) Delims(left, right string) *Template

Delimsは、指定された文字列にアクションデリミタを設定します。これは、 その後の Template.ParseTemplate.ParseFiles、または Template.ParseGlob への呼び出しで使用されます。 ネストしたテンプレート定義はこの設定を継承します。空のデリミタは、 対応するデフォルト({{または}})を表します。 戻り値はテンプレートなので、呼び出しはチェーンできます。

func (*Template) Execute

func (t *Template) Execute(wr io.Writer, data any) error

Executeは、解析されたテンプレートを指定されたデータオブジェクトに適用し、 出力をwrに書き込みます。 テンプレートの実行中またはその出力の書き込み中にエラーが発生した場合、 実行は停止しますが、部分的な結果がすでに出力ライターに書き込まれている可能性があります。 テンプレートは並行して安全に実行することができますが、並行実行がライターを共有する場合、 出力が交互になる可能性があります。

dataが reflect.Value の場合、テンプレートはreflect.Valueが保持する具体的な 値に適用されます。これは fmt.Print と同様です。

func (*Template) ExecuteTemplate

func (t *Template) ExecuteTemplate(wr io.Writer, name string, data any) error

ExecuteTemplateは、指定された名前を持つtに関連付けられたテンプレートを 指定されたデータオブジェクトに適用し、出力をwrに書き込みます。 テンプレートの実行中またはその出力の書き込み中にエラーが発生した場合、 実行は停止しますが、部分的な結果がすでに出力ライターに書き込まれている可能性があります。 テンプレートは並行して安全に実行することができますが、並行実行がライターを共有する場合、 出力が交互になる可能性があります。

func (*Template) Funcs

func (t *Template) Funcs(funcMap FuncMap) *Template

Funcsは、引数のマップの要素をテンプレートの関数マップに追加します。 これはテンプレートが解析される前に呼び出す必要があります。 マップの値が適切な戻り値型を持つ関数でない場合、または名前がテンプレート内の関数として 文法的に使用できない場合、パニックを起こします。 マップの要素を上書きすることは合法です。戻り値はテンプレートなので、呼び出しはチェーンできます。

func (*Template) Lookup

func (t *Template) Lookup(name string) *Template

Lookupは、tに関連付けられた指定された名前のテンプレートを返します。 そのようなテンプレートがないか、テンプレートが定義を持っていない場合はnilを返します。

func (*Template) Name

func (t *Template) Name() string

Nameはテンプレートの名前を返します。

func (*Template) New

func (t *Template) New(name string) *Template

Newは、与えられたテンプレートと同じデリミタを持つ新しい未定義のテンプレートを割り当てます。 この関連付けは推移的で、一つのテンプレートが{{template}}アクションで別のテンプレートを 呼び出すことを可能にします。

関連付けられたテンプレートは基礎となるデータを共有するため、テンプレートの構築は 並行して安全に行うことはできません。テンプレートが構築されたら、それらは並行して 実行することができます。

func (*Template) Option added in v1.5.0

func (t *Template) Option(opt ...string) *Template

Optionはテンプレートのオプションを設定します。オプションは 文字列によって記述され、単純な文字列または "key=value" の形式を取ります。 オプション文字列には最大で一つの等号が含まれていることができます。 オプション文字列が認識できないものや無効なものである場合、Optionはパニックを起こします。

Known options:

missingkey: Control the behavior during execution if a map is indexed with a key that is not present in the map.

"missingkey=default" or "missingkey=invalid"
	The default behavior: Do nothing and continue execution.
	If printed, the result of the index operation is the string
	"<no value>".
"missingkey=zero"
	The operation returns the zero value for the map type's element.
"missingkey=error"
	Execution stops immediately with an error.

func (*Template) Parse

func (t *Template) Parse(text string) (*Template, error)

Parseは、テキストをtのテンプレートボディとして解析します。 テキスト内の名前付きテンプレート定義({{define ...}}または{{block ...}}ステートメント)は、 tに関連付けられた追加のテンプレートを定義し、t自体の定義からは削除されます。

テンプレートは、Parseへの連続した呼び出しで再定義することができます。 本文が空白とコメントのみで構成されるテンプレート定義は空とみなされ、 既存のテンプレートの本文を置き換えません。 これにより、Parseを使用して新しい名前付きテンプレート定義を追加し、 メインのテンプレート本文を上書きすることなく行うことができます。

func (*Template) ParseFS added in v1.16.0

func (t *Template) ParseFS(fsys fs.FS, patterns ...string) (*Template, error)

ParseFSは、Template.ParseFilesTemplate.ParseGlob と似ていますが、ホストオペレーティングシステムの ファイルシステムの代わりにファイルシステムfsysから読み取ります。 それはグロブパターンのリストを受け入れます(path.Match を参照)。 (ほとんどのファイル名は、自分自身のみにマッチするグロブパターンとして機能します。)

func (*Template) ParseFiles

func (t *Template) ParseFiles(filenames ...string) (*Template, error)

ParseFilesは指定されたファイルを解析し、結果となるテンプレートを tと関連付けます。エラーが発生した場合、解析は停止し、返されるテンプレートはnilになります。 それ以外の場合はtです。ファイルは少なくとも1つ必要です。 ParseFilesによって作成されたテンプレートは、引数のファイルのベース名によって名付けられるため([filepath.Base] を参照)、 tは通常、ファイルの(ベース)名の1つを持つべきです。そうでない場合、tの 内容によっては、t.Executeが失敗する可能性があります。その場合は、 t.ExecuteTemplateを使用して有効なテンプレートを実行します。

異なるディレクトリにある同名の複数のファイルを解析するとき、 最後に指定されたものが結果となります。

func (*Template) ParseGlob

func (t *Template) ParseGlob(pattern string) (*Template, error)

ParseGlobは、パターンによって識別されたファイルのテンプレート定義を解析し、 結果となるテンプレートをtと関連付けます。ファイルは [filepath.Match] の セマンティクスに従ってマッチし、パターンは少なくとも1つのファイルと マッチしなければなりません。ParseGlobは、パターンによってマッチした ファイルのリストで Template.ParseFiles を呼び出すのと同等です。

異なるディレクトリにある同名の複数のファイルを解析するとき、 最後に指定されたものが結果となります。

func (*Template) Templates

func (t *Template) Templates() []*Template

Templatesは、tに関連付けられた定義済みテンプレートのスライスを返します。

Directories

Path Synopsis
パッケージparseは、text/templateおよびhtml/templateで定義されているテンプレートのパースツリーを構築します。
パッケージparseは、text/templateおよびhtml/templateで定義されているテンプレートのパースツリーを構築します。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL