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