github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/text/template/doc.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  /*
     6  パッケージtemplateは、テキスト出力を生成するためのデータ駆動型テンプレートを実装します。
     7  
     8  HTML出力を生成するには、[html/template] を参照してください。
     9  これはこのパッケージと同じインターフェースを持ち、
    10  特定の攻撃に対して自動的にHTML出力を保護します。
    11  
    12  テンプレートは、それをデータ構造に適用することで実行されます。テンプレート内の注釈は、
    13  データ構造の要素(通常は構造体のフィールドやマップのキー)を参照して、実行を制御し、
    14  表示する値を導き出します。テンプレートの実行は構造を歩き、カーソルを設定します。
    15  これはピリオド '.' で表され、"dot"と呼ばれ、実行が進行するにつれて構造内の現在の位置の
    16  値に設定されます。
    17  
    18  テンプレートの入力テキストは、任意の形式のUTF-8エンコードされたテキストです。
    19  "アクション" -- データ評価または制御構造 -- は "{{" と "}}" で区切られます。
    20  アクションの外側のすべてのテキストは、そのままの状態で出力にコピーされます。
    21  
    22  一度パースされると、テンプレートは並行して安全に実行することができますが、
    23  並行実行がWriterを共有している場合、出力は交互になる可能性があります。
    24  
    25  これは "17 items are made of wool" を出力する簡単な例です。
    26  
    27  	type Inventory struct {
    28  		Material string
    29  		Count    uint
    30  	}
    31  	sweaters := Inventory{"wool", 17}
    32  	tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
    33  	if err != nil { panic(err) }
    34  	err = tmpl.Execute(os.Stdout, sweaters)
    35  	if err != nil { panic(err) }
    36  
    37  より複雑な例は以下に示されています。
    38  
    39  テキストとスペース
    40  
    41  デフォルトでは、アクション間のすべてのテキストは、テンプレートが実行されるときに
    42  そのままコピーされます。例えば、上記の例の " items are made of " という文字列は、
    43  プログラムが実行されると標準出力に表示されます。
    44  
    45  しかし、テンプレートのソースコードを整形するために、アクションの左
    46  デリミタ(デフォルトでは "{{")が直後にマイナス記号と空白に続いている場合、
    47  直前のテキストからすべての末尾の空白がトリムされます。
    48  同様に、右デリミタ("}}")が空白とマイナス記号に先行されている場合、
    49  直後のテキストからすべての先頭の空白がトリムされます。
    50  これらのトリムマーカーでは、空白が存在しなければなりません:
    51  "{{- 3}}"は"{{3}}"と同じですが、直前のテキストをトリムします、一方
    52  "{{-3}}"は数値-3を含むアクションとして解析されます。
    53  
    54  例えば、ソースが以下のテンプレートを実行すると、
    55  
    56  	"{{23 -}} < {{- 45}}"
    57  
    58  生成される出力は以下のようになります。
    59  
    60  	"23<45"
    61  
    62  このトリミングにおいて、空白文字の定義はGoと同じです:スペース、水平タブ、キャリッジリターン、改行。
    63  
    64  アクション
    65  
    66  以下にアクションのリストを示します。"引数"と"パイプライン"は、
    67  データの評価であり、それぞれに続く対応するセクションで詳細に定義されています。
    68  
    69  */
    70  //	{{/* コメント */}}
    71  //	{{- /* 前後のテキストから空白をトリムしたコメント */ -}}
    72  //		コメント; 破棄されます。改行を含むことができます。
    73  //		コメントはネストできず、ここに示されているように
    74  //		デリミタで始まり終わらなければなりません。
    75  /*
    76  
    77  	{{パイプライン}}
    78  		パイプラインの値のデフォルトのテキスト表現(fmt.Printによって
    79  		印刷されるのと同じ)が出力にコピーされます。
    80  
    81  	{{if パイプライン}} T1 {{end}}
    82  		パイプラインの値が空の場合、出力は生成されません。
    83  		それ以外の場合、T1が実行されます。空の値はfalse、0、
    84  		任意のnilポインタまたはインターフェース値、および長さゼロの
    85  		任意の配列、スライス、マップ、または文字列です。
    86  		ドットは影響を受けません。
    87  
    88  	{{if パイプライン}} T1 {{else}} T0 {{end}}
    89  		パイプラインの値が空の場合、T0が実行されます。
    90  		それ以外の場合、T1が実行されます。ドットは影響を受けません。
    91  
    92  	{{if パイプライン}} T1 {{else if パイプライン}} T0 {{end}}
    93  		if-elseチェーンの見た目を簡素化するために、ifのelseアクションは
    94  		直接別のifを含むことができます。その効果は、以下を書くのと全く同じです。
    95  			{{if パイプライン}} T1 {{else}}{{if パイプライン}} T0 {{end}}{{end}}
    96  
    97  	{{range パイプライン}} T1 {{end}}
    98  		パイプラインの値は、配列、スライス、マップ、またはチャネルでなければなりません。
    99  		パイプラインの値の長さがゼロの場合、何も出力されません。
   100  		それ以外の場合、ドットは配列、スライス、またはマップの連続する要素に設定され、
   101  		T1が実行されます。値がマップで、キーが定義された順序を持つ基本型である場合、
   102  		要素はソートされたキーの順序で訪れます。
   103  
   104  	{{range パイプライン}} T1 {{else}} T0 {{end}}
   105  		パイプラインの値は、配列、スライス、マップ、またはチャネルでなければなりません。
   106  		パイプラインの値の長さがゼロの場合、ドットは影響を受けず、T0が実行されます。
   107  		それ以外の場合、ドットは配列、スライス、またはマップの連続する要素に設定され、
   108  		T1が実行されます。
   109  
   110  	{{break}}
   111  		最も内側の {{range pipeline}} ループが早期に終了し、
   112  		現在の反復を停止し、残りのすべての反復をバイパスします。
   113  
   114  	{{continue}}
   115  		最も内側の {{range pipeline}} ループの現在の反復が停止し、
   116  		ループは次の反復を開始します。
   117  
   118  	{{template "name"}}
   119  		指定された名前のテンプレートがnilデータで実行されます。
   120  
   121  	{{template "name" パイプライン}}
   122  		指定された名前のテンプレートが実行され、ドットはパイプラインの値に設定されます。
   123  
   124  	{{block "name" pipeline}} T1 {{end}}
   125  		ブロックは、テンプレートを定義するための省略形です
   126  			{{define "name"}} T1 {{end}}
   127  		そして、それをその場で実行します
   128  			{{template "name" pipeline}}
   129  		典型的な使用法は、一連のルートテンプレートを定義し、
   130  		それらをブロックテンプレートを再定義することでカスタマイズすることです。
   131  
   132  	{{with パイプライン}} T1 {{end}}
   133  		パイプラインの値が空の場合、出力は生成されません。
   134  		それ以外の場合、ドットはパイプラインの値に設定され、T1が実行されます。
   135  
   136  	{{with パイプライン}} T1 {{else}} T0 {{end}}
   137  		パイプラインの値が空の場合、ドットは影響を受けず、T0が実行されます。
   138  		それ以外の場合、ドットはパイプラインの値に設定され、T1が実行されます。
   139  
   140  	{{with pipeline}} T1 {{else with pipeline}} T0 {{end}}
   141  		with-elseチェーンの見た目を簡単にするために、withのelseアクションは
   142  		直接別のwithを含めることができます。その効果は、以下のように書くのと
   143  		全く同じです。
   144  			{{with pipeline}} T1 {{else}}{{with pipeline}} T0 {{end}}{{end}}
   145  
   146  
   147  Arguments
   148  
   149  引数は、以下のいずれかによって示される単純な値です。
   150  
   151  	- Goの構文に従ったブール値、文字列、文字、整数、浮動小数点数、虚数
   152  		または複素数の定数。これらはGoの型なし定数のように動作します。
   153  		Goと同様に、大きな整数定数が割り当てられたり関数に渡されたりするときに
   154  		オーバーフローするかどうかは、ホストマシンのintが32ビットか64ビットかに
   155  		依存することに注意してください。
   156  	- 型なしのGoのnilを表すキーワードnil。
   157  	- 文字 '.' (ピリオド):
   158  			.
   159  		結果はドットの値です。
   160  	- 変数名、これはドル記号に続く(可能性のある空の)英数字の文字列で、
   161  		例えば
   162  			$piOver2
   163  		または
   164  			$
   165  		結果は変数の値です。
   166  		変数については以下で説明します。
   167  	- データのフィールド名、これはピリオドに続く構造体でなければならず、
   168  		例えば
   169  			.Field
   170  		結果はフィールドの値です。フィールドの呼び出しはチェーン化することができます:
   171  			.Field1.Field2
   172  		フィールドは変数に対しても評価することができ、チェーン化も可能です:
   173  			$x.Field1.Field2
   174  	- データのキー名、これはマップでなければならず、ピリオドに続きます、
   175  		例えば
   176  			.Key
   177  		結果はキーによってインデックス付けされたマップ要素の値です。
   178  		キーの呼び出しはチェーン化し、フィールドと任意の深さで組み合わせることができます:
   179  			.Field1.Key1.Field2.Key2
   180  		キーは英数字の識別子でなければならないが、フィールド名とは異なり、
   181  		大文字で始まる必要はありません。
   182  		キーは変数に対しても評価することができ、チェーン化も可能です:
   183  			$x.key1.key2
   184  	- データの引数なしメソッドの名前、これはピリオドに続きます、
   185  		例えば
   186  			.Method
   187  		結果は、ドットをレシーバとしてメソッドを呼び出す値、dot.Method()です。
   188  		このようなメソッドは1つの戻り値(任意の型)または2つの戻り値を持つ必要があり、
   189  		2つ目はエラーです。
   190  		2つある場合で戻り値のエラーがnilでない場合、実行は終了し、
   191  		エラーがExecuteの値として呼び出し元に返されます。
   192  		メソッドの呼び出しはチェーン化し、フィールドとキーと任意の深さで組み合わせることができます:
   193  			.Field1.Key1.Method1.Field2.Key2.Method2
   194  		メソッドは変数に対しても評価することができ、チェーン化も可能です:
   195  			$x.Method1.Field
   196  	- 引数なし関数の名前、例えば
   197  			fun
   198  		結果は関数を呼び出す値、fun()です。戻り型と値はメソッドと同様に動作します。
   199  		関数と関数名については以下で説明します。
   200  	- グルーピングのための上記のインスタンスを括弧で囲んだもの。結果は
   201  		フィールドまたはマップキーの呼び出しによってアクセスできます。
   202  			print (.F1 arg1) (.F2 arg2)
   203  			(.StructValuedMethod "arg").Field
   204  
   205  引数は任意の型に評価することができます。もしポインタであれば、実装は必要に応じて
   206  自動的に基本型に間接参照します。
   207  評価が関数値を生成する場合、例えば構造体の関数値フィールドなど、関数は自動的に
   208  呼び出されませんが、ifアクションなどの真偽値として使用することができます。それを
   209  呼び出すには、以下で定義されているcall関数を使用します。
   210  
   211  パイプライン
   212  
   213  パイプラインは、"コマンド"の可能性のあるチェーン化されたシーケンスです。コマンドは、単純な
   214  値(引数)または関数またはメソッドの呼び出しで、複数の引数を持つ可能性があります:
   215  
   216  	Argument
   217  		結果は引数の評価値です。
   218  	.Method [Argument...]
   219  		メソッドは単独であるか、チェーンの最後の要素であることができますが、
   220  		チェーンの中間にあるメソッドとは異なり、引数を取ることができます。
   221  		結果は、引数を用いてメソッドを呼び出した値です:
   222  			dot.Method(Argument1, etc.)
   223  	functionName [Argument...]
   224  		結果は、名前に関連付けられた関数を呼び出した値です:
   225  			function(Argument1, etc.)
   226  		関数と関数名については以下で説明します。
   227  
   228  パイプラインは、パイプライン文字 '|' でコマンドのシーケンスを区切ることにより
   229  "チェーン化"することができます。チェーン化されたパイプラインでは、各コマンドの結果が
   230  次のコマンドの最後の引数として渡されます。パイプラインの最終コマンドの出力が
   231  パイプラインの値となります。
   232  
   233  コマンドの出力は、値が1つまたは2つ(2つ目の型はerror)のいずれかになります。
   234  もし2つ目の値が存在し、非nilと評価される場合、実行は終了し、そのエラーは
   235  Executeの呼び出し元に返されます。
   236  
   237  変数
   238  
   239  アクション内のパイプラインは、結果をキャプチャするために変数を初期化することができます。
   240  初期化は以下の構文を持ちます
   241  
   242  	$変数 := パイプライン
   243  
   244  ここで、$変数は変数の名前です。変数を宣言するアクションは出力を生成しません。
   245  
   246  以前に宣言された変数は、以下の構文を使用して割り当てることもできます
   247  
   248  	$変数 = パイプライン
   249  
   250  "range"アクションが変数を初期化する場合、変数は反復の連続する要素に設定されます。
   251  また、"range"は、カンマで区切られた2つの変数を宣言することもできます:
   252  
   253  	range $index, $element := パイプライン
   254  
   255  この場合、$indexと$elementは、配列/スライスのインデックスまたはマップキーと要素の
   256  連続する値に設定されます。ただし、変数が1つだけの場合、要素が割り当てられます。
   257  これはGoのrange節の慣習とは逆です。
   258  
   259  変数のスコープは、それが宣言された制御構造("if"、"with"、または"range")の
   260  "end"アクションまで、またはそのような制御構造がない場合はテンプレートの終わりまで
   261  広がります。テンプレートの呼び出しは、その呼び出し地点から変数を継承しません。
   262  
   263  実行が開始されると、$はExecuteに渡されたデータ引数、つまり、dotの開始値に設定されます。
   264  
   265  例
   266  
   267  以下は、パイプラインと変数を示す一行のテンプレートの例です。
   268  すべてが引用符で囲まれた単語 "output" を生成します:
   269  
   270  	{{"\"output\""}}
   271  		A string constant.
   272  	{{`"output"`}}
   273  		A raw string constant.
   274  	{{printf "%q" "output"}}
   275  		A function call.
   276  	{{"output" | printf "%q"}}
   277  		A function call whose final argument comes from the previous
   278  		command.
   279  	{{printf "%q" (print "out" "put")}}
   280  		A parenthesized argument.
   281  	{{"put" | printf "%s%s" "out" | printf "%q"}}
   282  		A more elaborate call.
   283  	{{"output" | printf "%s" | printf "%q"}}
   284  		A longer chain.
   285  	{{with "output"}}{{printf "%q" .}}{{end}}
   286  		A with action using dot.
   287  	{{with $x := "output" | printf "%q"}}{{$x}}{{end}}
   288  		A with action that creates and uses a variable.
   289  	{{with $x := "output"}}{{printf "%q" $x}}{{end}}
   290  		A with action that uses the variable in another action.
   291  	{{with $x := "output"}}{{$x | printf "%q"}}{{end}}
   292  		The same, but pipelined.
   293  
   294  関数
   295  
   296  実行中、関数は2つの関数マップで見つけられます:まずテンプレート内、次にグローバル関数マップ内です。
   297  デフォルトでは、テンプレート内には関数は定義されていませんが、Funcsメソッドを使用して追加することができます。
   298  
   299  事前定義されたグローバル関数は以下のように名付けられます。
   300  
   301  	and
   302  		引数のブール型のANDを返します。つまり、最初の空の引数または最後の引数を返します。
   303  		つまり、"and x y"は"if x then y else x"と同じように動作します。
   304  		評価は引数を左から右へと進み、結果が決定した時点で返ります。
   305  	call
   306  		最初の引数(関数である必要があります)を、残りの引数をパラメータとして呼び出した結果を返します。
   307  		したがって、"call .X.Y 1 2"はGoの表記ではdot.X.Y(1, 2)となります。ここで
   308  		Yは関数値フィールド、マップエントリ、またはそれに類するものです。
   309  		最初の引数は、関数型の値を生成する評価の結果でなければなりません
   310  		(printのような事前定義された関数とは異なります)。関数は
   311  		1つまたは2つの結果値を返す必要があり、2つ目の型はerrorです。引数が関数と一致しない場合や
   312  		返されたエラー値が非nilの場合、実行は停止します。
   313  	html
   314  		引数のテキスト表現のエスケープされたHTML相当を返します。この関数は
   315  		html/templateでは利用できません、いくつかの例外を除いて。
   316  	index
   317  		最初の引数を次の引数でインデックス化した結果を返します。
   318  		したがって、"index x 1 2 3"はGoの構文ではx[1][2][3]となります。
   319  		各インデックス化されたアイテムは、マップ、スライス、または配列でなければなりません。
   320  	slice
   321  		sliceは、最初の引数を残りの引数でスライスした結果を返します。
   322  		したがって、"slice x 1 2"はGoの構文ではx[1:2]、"slice x"はx[:]、
   323  		"slice x 1"はx[1:]、そして"slice x 1 2 3"はx[1:2:3]となります。
   324  		最初の引数は、文字列、スライス、または配列でなければなりません。
   325  	js
   326  		引数のテキスト表現のエスケープされたJavaScript相当を返します。
   327  	len
   328  		引数の整数長を返します。
   329  	not
   330  		単一の引数のブール否定を返します。
   331  	or
   332  		引数のブール型のORを返します。つまり、最初の非空の引数または最後の引数を返します。
   333  		したがって、"or x y"は"if x then x else y"と同じように動作します。
   334  		評価は引数を左から右へと進み、結果が決定した時点で返ります。
   335  	print
   336  		fmt.Sprintのエイリアス
   337  	printf
   338  		fmt.Sprintfのエイリアス
   339  	println
   340  		fmt.Sprintlnのエイリアス
   341  	urlquery
   342  		その引数のテキスト表現のエスケープされた値を、URLクエリに埋め込むのに適した形で返します。
   343  		この関数はhtml/templateでは利用できません、いくつかの例外を除いて。
   344  
   345  ブール関数は、ゼロ値をfalse、非ゼロ値をtrueとして取ります。
   346  
   347  また、関数として定義された一連の二項比較演算子もあります:
   348  
   349  	eq
   350  		arg1 == arg2のブール型の真偽値を返します
   351  	ne
   352  		arg1 != arg2のブール型の真偽値を返します
   353  	lt
   354  		arg1 < arg2のブール型の真偽値を返します
   355  	le
   356  		arg1 <= arg2のブール型の真偽値を返します
   357  	gt
   358  		arg1 > arg2のブール型の真偽値を返します
   359  	ge
   360  		arg1 >= arg2のブール型の真偽値を返します
   361  
   362  よりシンプルな多方向の等価性テストのために、eq(のみ)は2つ以上の
   363  引数を受け入れ、2番目以降を最初のものと比較し、実質的に以下を返します
   364  
   365  	arg1==arg2 || arg1==arg3 || arg1==arg4 ...
   366  
   367  (ただし、Goの||とは異なり、eqは関数呼び出しであり、すべての
   368  引数が評価されます。)
   369  
   370  比較関数は、Goが比較可能と定義している任意の型の値で動作します。
   371  基本的な型、例えば整数については、ルールが緩和されています:
   372  サイズと正確な型は無視され、任意の整数値、符号付きまたは符号なし、
   373  は他の任意の整数値と比較することができます。(算術値が比較され、
   374  ビットパターンではないので、すべての負の整数はすべての符号なし整数より小さいです。)
   375  しかし、通常通り、intをfloat32などと比較することはできません。
   376  
   377  関連付けられたテンプレート
   378  
   379  各テンプレートは、作成時に指定された文字列によって名付けられます。また、各
   380  テンプレートは、名前で呼び出すことができる他のテンプレートとゼロ以上関連付けられています。
   381  そのような関連付けは推移的であり、テンプレートの名前空間を形成します。
   382  
   383  テンプレートは、テンプレート呼び出しを使用して、別の関連付けられた
   384  テンプレートをインスタンス化することができます。上記の "template" アクションの説明を参照してください。
   385  名前は、呼び出しを含むテンプレートに関連付けられたテンプレートの名前でなければなりません。
   386  
   387  ネストしたテンプレート定義
   388  
   389  テンプレートを解析するとき、別のテンプレートが定義され、解析中の
   390  テンプレートと関連付けられることがあります。テンプレート定義は、
   391  Goプログラムのグローバル変数のように、テンプレートのトップレベルに
   392  現れなければなりません。
   393  
   394  そのような定義の構文は、各テンプレート宣言を
   395  "define"と"end"アクションで囲むことです。
   396  
   397  "define"アクションは、文字列定数を提供することで作成されるテンプレートの名前を指定します。
   398  以下に簡単な例を示します:
   399  
   400  	{{define "T1"}}ONE{{end}}
   401  	{{define "T2"}}TWO{{end}}
   402  	{{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
   403  	{{template "T3"}}
   404  
   405  これは、T1とT2という2つのテンプレートを定義し、実行時に他の2つを呼び出す
   406  T3という3つ目のテンプレートを定義します。最後にT3を呼び出します。このテンプレートが
   407  実行されると、以下のテキストが生成されます
   408  
   409  	ONE TWO
   410  
   411  構造上、テンプレートは一つの関連付けのみに存在することができます。もしテンプレートを
   412  複数の関連付けからアドレス可能にする必要がある場合、テンプレート定義は複数回パースされて
   413  異なる*Template値を作成するか、[Template.Clone] または [Template.AddParseTree] メソッドでコピーされなければなりません。
   414  
   415  Parseは、関連する複数のテンプレートを組み立てるために複数回呼び出すことができます。
   416  関連するテンプレートがファイルに保存されている場合のパースを簡単に行うための
   417  [ParseFiles]、[ParseGlob]、[Template.ParseFiles] および [Template.ParseGlob] を参照してください。
   418  
   419  テンプレートは直接実行するか、または名前で識別される関連付けられたテンプレートを実行する
   420  ExecuteTemplateを通じて実行することができます。上記の例を呼び出すために、私たちは
   421  以下のように書くかもしれません。
   422  
   423  	err := tmpl.Execute(os.Stdout, "no data needed")
   424  	if err != nil {
   425  		log.Fatalf("execution failed: %s", err)
   426  	}
   427  
   428  or to invoke a particular template explicitly by name,
   429  
   430  	err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed")
   431  	if err != nil {
   432  		log.Fatalf("execution failed: %s", err)
   433  	}
   434  
   435  */
   436  package template