樣板函數列表

Helm 包含許多您可以在樣板中使用的樣板函數。它們在此列出並按以下類別細分

邏輯和流程控制函數

Helm 包含許多邏輯和控制流程函數,包括 andcoalescedefaultemptyeqfailgegtleltnenotorrequired

and

傳回兩個或多個參數的布林 AND(第一個空參數或最後一個參數)。

and .Arg1 .Arg2

or

傳回兩個或多個參數的布林 OR(第一個非空參數或最後一個參數)。

or .Arg1 .Arg2

not

傳回其參數的布林否定。

not .Arg

eq

傳回參數的布林等式(例如,Arg1 == Arg2)。

eq .Arg1 .Arg2

ne

傳回參數的布林不等式(例如,Arg1 != Arg2)

ne .Arg1 .Arg2

lt

如果第一個參數小於第二個參數,則傳回布林值 true。否則傳回 false(例如,Arg1 < Arg2)。

lt .Arg1 .Arg2

le

如果第一個參數小於或等於第二個參數,則傳回布林值 true。否則傳回 false(例如,Arg1 <= Arg2)。

le .Arg1 .Arg2

gt

如果第一個參數大於第二個參數,則傳回布林值 true。否則傳回 false(例如,Arg1 > Arg2)。

gt .Arg1 .Arg2

ge

如果第一個參數大於或等於第二個參數,則傳回布林值 true。否則傳回 false(例如,Arg1 >= Arg2)。

ge .Arg1 .Arg2

default

要設定簡單的預設值,請使用 default

default "foo" .Bar

在上面,如果 .Bar 評估為非空值,則將使用它。但如果它是空的,則會改為傳回 foo

「空」的定義取決於類型

  • 數值:0
  • 字串:""
  • 列表:[]
  • 字典:{}
  • 布林值:false
  • 並且始終為 nil(也稱為 null)

對於結構,沒有空的定義,因此結構永遠不會傳回預設值。

required

使用 required 指定必須設定的值

required "A valid foo is required!" .Bar

如果 .Bar 為空或未定義(請參閱 default 了解如何評估),則樣板將不會渲染並將改為傳回提供的錯誤訊息。

empty

如果給定值被視為空,則 empty 函數傳回 true,否則傳回 false。空值列在 default 部分中。

empty .Foo

請注意,在 Go 樣板條件中,會為您計算空值。因此,您很少需要 if not empty .Foo。相反,只需使用 if .Foo

fail

無條件地傳回一個空的 string 和一個帶有指定文字的 error。這在其他條件已確定樣板渲染應失敗的情況下很有用。

fail "Please accept the end user license agreement"

coalesce

coalesce 函數接受一個值列表並傳回第一個非空值。

coalesce 0 1 2

上面傳回 1

此函數適用於掃描多個變數或值

coalesce .name .parent.name "Matt"

上面將首先檢查 .name 是否為空。如果不是,它將傳回該值。如果它空的,coalesce 將評估 .parent.name 是否為空。最後,如果 .name.parent.name 都為空,它將傳回 Matt

ternary

ternary 函數接受兩個值和一個測試值。如果測試值為真,則將傳回第一個值。如果測試值為空,則將傳回第二個值。這類似於 C 語言和其他程式語言中的三元運算符。

真測試值

ternary "foo" "bar" true

or

true | ternary "foo" "bar"

上面傳回 "foo"

假測試值

ternary "foo" "bar" false

or

false | ternary "foo" "bar"

上面傳回 "bar"

字串函數

Helm 包含以下字串函數:abbrevabbrevbothcamelcasecatcontainshasPrefixhasSuffixindentinitialskebabcaselowernindentnospacepluralprintprintfprintlnquoterandAlpharandAlphaNumrandAsciirandNumericrepeatreplaceshufflesnakecasesquotesubstrswapcasetitletrimtrimAlltrimPrefixtrimSuffixtruncuntitleupperwrapwrapWith

print

從其各部分的組合傳回一個字串。

print "Matt has " .Dogs " dogs"

非字串的類型會在可能的情況下轉換為字串。

請注意,當兩個相鄰的參數不是字串時,它們之間會添加一個空格。

println

工作方式與 print 相同,但在結尾添加一個新行。

printf

根據格式化字串和按順序傳遞給它的參數傳回一個字串。

printf "%s has %d dogs." .Name .NumberDogs

要使用的佔位符取決於傳入參數的類型。這包括

通用

  • %v 預設格式的值
    • 列印字典時,加號標誌 (%+v) 會添加欄位名稱
  • %% 字面百分號;不消耗任何值

布林值

  • %t 單詞 true 或 false

整數

  • %b 基數 2
  • %c 由相應的 Unicode 代碼點表示的字元
  • %d 基數 10
  • %o 基數 8
  • %O 基數 8,帶有 0o 前綴
  • %q 安全轉義的單引號字元文字
  • %x 基數 16,a-f 使用小寫字母
  • %X 基數 16,A-F 使用大寫字母
  • %U Unicode 格式:U+1234;與 "U+%04X" 相同

浮點數和複數成分

  • %b 指數為 2 的冪的十進制非科學計數法,例如 -123456p-78
  • %e 科學計數法,例如 -1.234456e+78
  • %E 科學計數法,例如 -1.234456E+78
  • %f 小數點但沒有指數,例如 123.456
  • %F %f 的同義詞
  • %g 對於大指數為 %e,否則為 %f。
  • %G 對於大指數為 %E,否則為 %F
  • %x 十六進制表示法(帶有 2 的十進制冪指數),例如 -0x1.23abcp+20
  • %X 大寫十六進制表示法,例如 -0X1.23ABCP+20

字串和位元組切片(使用這些動詞等效處理)

  • %s 字串或切片的未解釋位元組
  • %q 安全轉義的雙引號字串
  • %x 16 進位,小寫,每個位元組兩個字元
  • %X 16 進位,大寫,每個位元組兩個字元

Slice(切片)

  • %p 第 0 個元素的地址,以 16 進位表示法,前面加上 0x

trim(修剪)

trim 函數會移除字串兩側的空白字元

trim "   hello    "

以上程式碼會產生 hello

trimAll(修剪全部)

移除字串前後指定的字元

trimAll "$" "$5.00"

以上程式碼會傳回 5.00(作為字串)。

trimPrefix(修剪前綴)

僅修剪字串的前綴

trimPrefix "-" "-hello"

以上程式碼會傳回 hello

trimSuffix(修剪後綴)

僅修剪字串的後綴

trimSuffix "-" "hello-"

以上程式碼會傳回 hello

lower(轉小寫)

將整個字串轉換為小寫

lower "HELLO"

以上程式碼會傳回 hello

upper(轉大寫)

將整個字串轉換為大寫

upper "hello"

以上程式碼會傳回 HELLO

title(標題化)

轉換為標題大小寫

title "hello world"

以上程式碼會傳回 Hello World

untitle(取消標題化)

移除標題大小寫。untitle "Hello World" 會產生 hello world

repeat(重複)

將字串重複多次

repeat 3 "hello"

以上程式碼會傳回 hellohellohello

substr(子字串)

從字串中取得子字串。它需要三個參數

  • start(起始位置,整數)
  • end(結束位置,整數)
  • string(字串)
substr 0 5 "hello world"

以上程式碼會傳回 hello

nospace(無空格)

移除字串中的所有空白字元。

nospace "hello w o r l d"

以上程式碼會傳回 helloworld

trunc(截斷)

截斷字串

trunc 5 "hello world"

以上程式碼會產生 hello

trunc -5 "hello world"

以上程式碼會產生 world

abbrev(縮寫)

使用省略號 (...) 截斷字串

參數

  • 最大長度
  • 字串
abbrev 5 "hello world"

以上程式碼會傳回 he...,因為它會將省略號的寬度計入最大長度。

abbrevboth(兩側縮寫)

縮寫兩側

abbrevboth 5 10 "1234 5678 9123"

以上程式碼會產生 ...5678...

它需要

  • 左側偏移量
  • 最大長度
  • 字串

initials(首字母縮寫)

給定多個單字,取每個單字的第一個字母並組合。

initials "First Try"

以上程式碼會傳回 FT

randAlphaNum、randAlpha、randNumeric 和 randAscii

這四個函數會產生密碼學上安全的(使用 crypto/rand)隨機字串,但具有不同的基本字元集

  • randAlphaNum 使用 0-9a-zA-Z
  • randAlpha 使用 a-zA-Z
  • randNumeric 使用 0-9
  • randAscii 使用所有可列印的 ASCII 字元

它們 masing-masing 只需要一個參數:字串的整數長度。

randNumeric 3

以上程式碼會產生一個包含三位數字的隨機字串。

wrap(換行)

在指定的欄數處換行文字

wrap 80 $someText

以上程式碼會在 80 個欄數處換行 $someText 中的字串。

wrapWith(使用指定字元換行)

wrapWith 的功能與 wrap 相同,但允許您指定用於換行的字串。(wrap 使用 \n

wrapWith 5 "\t" "Hello World"

以上程式碼會產生 Hello World(其中空白字元是 ASCII Tab 字元)

contains(包含)

測試一個字串是否包含在另一個字串中

contains "cat" "catch"

以上程式碼會傳回 true,因為 catch 包含 cat

hasPrefix 和 hasSuffix(具有前綴和後綴)

hasPrefixhasSuffix 函數會測試字串是否具有指定的前綴或後綴

hasPrefix "cat" "catch"

以上程式碼會傳回 true,因為 catch 具有前綴 cat

quote 和 squote(雙引號和單引號)

這些函數會將字串用雙引號 (quote) 或單引號 (squote) 包起來。

cat(串接)

cat 函數會將多個字串串接成一個,並以空格分隔

cat "hello" "beautiful" "world"

以上程式碼會產生 hello beautiful world

indent(縮排)

indent 函數會將指定字串中的每一行縮排到指定的縮排寬度。這在對齊多行字串時很有用

indent 4 $lots_of_text

以上程式碼會將每一行文字縮排 4 個空格字元。

nindent(新增一行並縮排)

nindent 函數與 indent 函數相同,但會在字串開頭加上一個新行。

nindent 4 $lots_of_text

以上程式碼會將每一行文字縮排 4 個空格字元,並在開頭加上一個新行。

replace(取代)

執行簡單的字串取代。

它需要三個參數

  • 要取代的字串
  • 取代成的字串
  • 來源字串
"I Am Henry VIII" | replace " " "-"

以上程式碼會產生 I-Am-Henry-VIII

plural(複數化)

將字串複數化。

len $fish | plural "one anchovy" "many anchovies"

在以上程式碼中,如果字串的長度為 1,則會印出第一個參數 (one anchovy)。否則,會印出第二個參數 (many anchovies)。

參數為

  • 單數字串
  • 複數字串
  • 長度整數

注意:Helm 目前不支援具有更複雜複數化規則的語言。而且 0 被視為複數,因為英語將其視為複數 (zero anchovies)。

snakecase(蛇形命名法)

將字串從 camelCase 轉換為 snake_case。

snakecase "FirstName"

以上程式碼會產生 first_name

camelcase(駝峰命名法)

將字串從 snake_case 轉換為 CamelCase

camelcase "http_server"

以上程式碼會產生 HttpServer

kebabcase(烤肉串命名法)

將字串從 camelCase 轉換為 kebab-case。

kebabcase "FirstName"

以上程式碼會產生 first-name

swapcase(大小寫交換)

使用基於單字的演算法交換字串的大小寫。

轉換演算法

  • 大寫字元轉換為小寫
  • 標題大小寫字元轉換為小寫
  • 空白字元後或開頭的小寫字元轉換為標題大小寫
  • 其他小寫字元轉換為大寫
  • 空白字元由 unicode.IsSpace(char) 定義
swapcase "This Is A.Test"

以上程式碼會產生 tHIS iS a.tEST

shuffle(洗牌)

洗牌字串。

shuffle "hello"

以上程式碼會將 hello 中的字母隨機排列,可能會產生 oelhl

類型轉換函數

Helm 提供以下類型轉換函數

  • atoi:將字串轉換為整數。
  • float64:轉換為 float64
  • int:轉換為系統寬度的 int
  • int64:轉換為 int64
  • toDecimal:將 Unix 八進位制轉換為 int64
  • toString:轉換為字串。
  • toStrings:將列表、切片或陣列轉換為字串列表。
  • toJson (mustToJson):將列表、切片、陣列、字典或物件轉換為 JSON。
  • toPrettyJson (mustToPrettyJson):將列表、切片、陣列、字典或物件轉換為縮排的 JSON。
  • toRawJson (mustToRawJson):將列表、切片、陣列、字典或物件轉換為 HTML 字元未逸出的 JSON。
  • fromYaml:將 YAML 字串轉換為物件。
  • fromJson:將 JSON 字串轉換為物件。
  • fromJsonArray:將 JSON 陣列轉換為列表。
  • toYaml:將列表、切片、陣列、字典或物件轉換為縮排的 yaml,可用於從任何來源複製 yaml 塊。此函數等效於 GoLang yaml.Marshal 函數,請參閱此處的文檔:https://pkg.go.dev/gopkg.in/yaml.v2#Marshal
  • toToml:將列表、切片、陣列、字典或物件轉換為 toml,可用於從任何來源複製 toml 塊。
  • fromYamlArray:將 YAML 陣列轉換為列表。

只有 atoi 要求輸入是特定類型。其他函數會嘗試將任何類型轉換為目標類型。例如,int64 可以將浮點數轉換為整數,也可以將字串轉換為整數。

toStrings

給定一個類似列表的集合,產生一個字串切片。

list 1 2 3 | toStrings

以上程式碼會將 1 轉換為 "1",將 2 轉換為 "2",依此類推,然後將它們作為列表傳回。

toDecimal

給定 Unix 八進位制權限,產生一個十進位制數。

"0777" | toDecimal

以上程式碼會將 0777 轉換為 511,並將該值作為 int64 傳回。

toJson、mustToJson

toJson 函數會將項目編碼為 JSON 字串。如果項目無法轉換為 JSON,則該函數會傳回空字串。如果項目無法編碼為 JSON,則 mustToJson 會傳回錯誤。

toJson .Item

以上程式碼會傳回 .Item 的 JSON 字串表示形式。

toPrettyJson、mustToPrettyJson

toPrettyJson 函數會將項目編碼為漂亮的(縮排的)JSON 字串。

toPrettyJson .Item

以上程式碼會傳回 .Item 的縮排 JSON 字串表示形式。

toRawJson、mustToRawJson

toRawJson 函數會將項目編碼為 HTML 字元未逸出的 JSON 字串。

toRawJson .Item

以上程式碼會傳回 .Item 的未逸出 JSON 字串表示形式。

fromYaml

fromYaml 函數會接收 YAML 字串,並傳回一個可在模板中使用的物件。

檔案位於:yamls/person.yaml

name: Bob
age: 25
hobbies:
  - hiking
  - fishing
  - cooking
{{- $person := .Files.Get "yamls/person.yaml" | fromYaml }}
greeting: |
  Hi, my name is {{ $person.name }} and I am {{ $person.age }} years old.
  My hobbies are {{ range $person.hobbies }}{{ . }} {{ end }}.  

fromJson

fromJson 函數會接收 JSON 字串,並傳回一個可在模板中使用的物件。

檔案位於:jsons/person.json

{
  "name": "Bob",
  "age": 25,
  "hobbies": [
    "hiking",
    "fishing",
    "cooking"
  ]
}
{{- $person := .Files.Get "jsons/person.json" | fromJson }}
greeting: |
  Hi, my name is {{ $person.name }} and I am {{ $person.age }} years old.
  My hobbies are {{ range $person.hobbies }}{{ . }} {{ end }}.  

fromJsonArray

fromJsonArray 函數會接收 JSON 陣列,並傳回一個可在模板中使用的列表。

檔案位於:jsons/people.json

[
 { "name": "Bob","age": 25 },
 { "name": "Ram","age": 16 }
]
{{- $people := .Files.Get "jsons/people.json" | fromJsonArray }}
{{- range $person := $people }}
greeting: |
    Hi, my name is {{ $person.name }} and I am {{ $person.age }} years old.
{{ end }}

fromYamlArray

fromYamlArray 函數會接收 YAML 陣列,並傳回一個可在模板中使用的列表。

檔案位於:yamls/people.yml

- name: Bob
  age: 25
- name: Ram
  age: 16
{{- $people := .Files.Get "yamls/people.yml" | fromYamlArray }}
{{- range $person := $people }}
greeting: |
    Hi, my name is {{ $person.name }} and I am {{ $person.age }} years old.
{{ end }}

正則表達式

Helm 包含以下正則表達式函數:regexFind (mustRegexFind)regexFindAll (mustRegexFindAll)regexMatch (mustRegexMatch)regexReplaceAll (mustRegexReplaceAll)regexReplaceAllLiteral (mustRegexReplaceAllLiteral)regexSplit (mustRegexSplit)

regexMatch、mustRegexMatch

如果輸入字串包含任何與正則表達式匹配的內容,則傳回 true。

regexMatch "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$" "test@acme.com"

以上程式碼會產生 true

如果出現問題,regexMatch 會發生恐慌,如果出現問題,mustRegexMatch 會向模板引擎傳回錯誤。

regexFindAll、mustRegexFindAll

傳回輸入字串中所有與正則表達式匹配的切片。最後一個參數 n 決定要傳回的子字串數量,其中 -1 表示傳回所有匹配項

regexFindAll "[2,4,6,8]" "123456789" -1

以上程式碼會產生 [2 4 6 8]

如果出現問題,regexFindAll 會發生恐慌,如果出現問題,mustRegexFindAll 會向模板引擎傳回錯誤。

regexFind、mustRegexFind

傳回輸入字串中正則表達式的第一個(最左側)匹配項

regexFind "[a-zA-Z][1-9]" "abcd1234"

以上程式碼會產生 d1

如果出現問題,regexFind 會發生恐慌,如果出現問題,mustRegexFind 會向模板引擎傳回錯誤。

regexReplaceAll、mustRegexReplaceAll

傳回輸入字串的副本,將 Regexp 的匹配項替換為替換字串 replacement。在字串替換內,$ 符號的解釋與 Expand 中相同,因此例如 $1 表示第一個子匹配項的文字

regexReplaceAll "a(x*)b" "-ab-axxb-" "${1}W"

以上程式碼會產生 -W-xxW-

如果出現問題,regexReplaceAll 會發生恐慌,如果出現問題,mustRegexReplaceAll 會向模板引擎傳回錯誤。

regexReplaceAllLiteral、mustRegexReplaceAllLiteral

傳回輸入字串的副本,將 Regexp 的匹配項替換為替換字串 replacement。替換字串會直接替換,而不使用 Expand

regexReplaceAllLiteral "a(x*)b" "-ab-axxb-" "${1}"

以上程式碼會產生 -${1}-${1}-

如果出現問題,regexReplaceAllLiteral 會發生恐慌,如果出現問題,mustRegexReplaceAllLiteral 會向模板引擎傳回錯誤。

regexSplit、mustRegexSplit

將輸入字串切片成由表達式分隔的子字串,並傳回這些表達式匹配項之間的子字串切片。最後一個參數 n 決定要傳回的子字串數量,其中 -1 表示傳回所有匹配項

regexSplit "z+" "pizza" -1

以上程式碼會產生 [pi a]

如果出現問題,regexSplit 會發生恐慌,如果出現問題,mustRegexSplit 會向模板引擎傳回錯誤。

密碼學和安全函數

Helm 提供了一些進階的密碼學函數。它們包括 adler32sumbuildCustomCertdecryptAESderivePasswordencryptAESgenCAgenPrivateKeygenSelfSignedCertgenSignedCerthtpasswdsha1sumsha256sum

sha1sum

sha1sum 函數接收一個字串,並計算其 SHA1 摘要。

sha1sum "Hello world!"

sha256sum

sha256sum 函數接收一個字串,並計算其 SHA256 摘要。

sha256sum "Hello world!"

以上將以「ASCII 編碼」格式計算 SHA 256 總和,此格式可以安全地列印。

adler32sum

adler32sum 函數接收一個字串,並計算其 Adler-32 校驗和。

adler32sum "Hello world!"

htpasswd

htpasswd 函數接收 usernamepassword,並產生密碼的 bcrypt 雜湊。結果可用於 Apache HTTP 伺服器 上的基本身份驗證。

htpasswd "myUser" "myPassword"

請注意,直接在範本中儲存密碼是不安全的。

derivePassword

derivePassword 函數可用於根據一些共享的「主密碼」約束來衍生特定密碼。此演算法有 詳細規範

derivePassword 1 "long" "password" "user" "example.com"

請注意,將零件直接儲存在範本中被認為是不安全的。

genPrivateKey

genPrivateKey 函數會產生一個編碼成 PEM 區塊的新私鑰。

它會將以下其中一個值作為其第一個參數

  • ecdsa:產生橢圓曲線 DSA 金鑰 (P256)
  • dsa:產生 DSA 金鑰 (L2048N256)
  • rsa:產生 RSA 4096 金鑰

buildCustomCert

buildCustomCert 函數允許自訂憑證。

它接受以下字串參數

  • 以 Base64 編碼的 PEM 格式憑證
  • 以 Base64 編碼的 PEM 格式私鑰

它會傳回具有以下屬性的憑證物件

  • Cert:PEM 編碼的憑證
  • Key:PEM 編碼的私鑰

範例

$ca := buildCustomCert "base64-encoded-ca-crt" "base64-encoded-ca-key"

請注意,傳回的物件可以傳遞給 genSignedCert 函數,以使用此 CA 簽署憑證。

genCA

genCA 函數會產生一個新的、自我簽署的 x509 憑證授權單位。

它接受以下參數

  • 主體的通用名稱 (cn)
  • 憑證有效期(以天為單位)

它會傳回具有以下屬性的物件

  • Cert:PEM 編碼的憑證
  • Key:PEM 編碼的私鑰

範例

$ca := genCA "foo-ca" 365

請注意,傳回的物件可以傳遞給 genSignedCert 函數,以使用此 CA 簽署憑證。

genSelfSignedCert

genSelfSignedCert 函數會產生一個新的、自我簽署的 x509 憑證。

它接受以下參數

  • 主體的通用名稱 (cn)
  • IP 的選用清單;可以為 nil
  • 替代 DNS 名稱的選用清單;可以為 nil
  • 憑證有效期(以天為單位)

它會傳回具有以下屬性的物件

  • Cert:PEM 編碼的憑證
  • Key:PEM 編碼的私鑰

範例

$cert := genSelfSignedCert "foo.com" (list "10.0.0.1" "10.0.0.2") (list "bar.com" "bat.com") 365

genSignedCert

genSignedCert 函數會產生一個新的、由指定 CA 簽署的 x509 憑證。

它接受以下參數

  • 主體的通用名稱 (cn)
  • IP 的選用清單;可以為 nil
  • 替代 DNS 名稱的選用清單;可以為 nil
  • 憑證有效期(以天為單位)
  • CA(參見 genCA

範例

$ca := genCA "foo-ca" 365
$cert := genSignedCert "foo.com" (list "10.0.0.1" "10.0.0.2") (list "bar.com" "bat.com") 365 $ca

encryptAES

encryptAES 函數使用 AES-256 CBC 加密文字,並傳回以 Base64 編碼的字串。

encryptAES "secretkey" "plaintext"

decryptAES

decryptAES 函數接收由 AES-256 CBC 演算法編碼的 Base64 字串,並傳回解碼的文字。

"30tEfhuJSVRhpG97XCuWgz2okj7L8vQ1s6V9zVUPeDQ=" | decryptAES "secretkey"

日期函數

Helm 包含以下您可以在範本中使用的日期函數:agodatedateInZonedateModify (mustDateModify)durationdurationRoundhtmlDatehtmlDateInZonenowtoDate (mustToDate)unixEpoch

now

目前的日期/時間。將此與其他日期函數一起使用。

ago

ago 函數傳回從時間開始的持續時間。現在以秒解析度。

ago .CreatedAt

time.Duration String() 格式傳回

2h34m7s

date

date 函數格式化日期。

將日期格式化為 年-月-日

now | date "2006-01-02"

Go 中的日期格式化 略有不同

簡而言之,將此作為基準日期

Mon Jan 2 15:04:05 MST 2006

以您想要的格式編寫。以上,2006-01-02 是同一天,但採用我們想要的格式。

dateInZone

date 相同,但帶有時區。

dateInZone "2006-01-02" (now) "UTC"

duration

將給定的秒數格式化為 time.Duration

這會傳回 1 分 35 秒

duration 95

durationRound

將給定的持續時間四捨五入到最重要的單位。字串和 time.Duration 會被解析為持續時間,而 time.Time 則會計算為自該時間以來的持續時間。

這會傳回 2 小時

durationRound "2h10m5s"

這會傳回 3 個月

durationRound "2400h10m5s"

unixEpoch

傳回自 Unix 紀元以來 time.Time 的秒數。

now | unixEpoch

dateModify, mustDateModify

dateModify 接受修改和日期,並傳回時間戳記。

從目前時間減去一小時三十秒

now | dateModify "-1.5h"

如果修改格式錯誤,dateModify 將傳回未修改的日期。否則,mustDateModify 將傳回錯誤。

htmlDate

htmlDate 函數格式化日期,以插入 HTML 日期選擇器輸入欄位。

now | htmlDate

htmlDateInZone

與 htmlDate 相同,但帶有時區。

htmlDateInZone (now) "UTC"

toDate, mustToDate

toDate 將字串轉換為日期。第一個參數是日期佈局,第二個參數是日期字串。如果字串無法轉換,它會傳回零值。如果字串無法轉換,mustToDate 將傳回錯誤。

當您想要將字串日期轉換為另一種格式(使用管道)時,這很有用。以下範例將「2017-12-31」轉換為「31/12/2017」。

toDate "2006-01-02" "2017-12-31" | date "02/01/2006"

字典和字典函數

Helm 提供了一種稱為 dict(「dictionary」的縮寫,如同 Python 中的用法)的鍵/值儲存類型。dict 是一種*無序*類型。

字典的鍵*必須是字串*。但是,值可以是任何類型,甚至是另一個 dictlist

list 不同,dict 不是不可變的。setunset 函數將修改字典的內容。

Helm 提供以下函數來支援使用字典:deepCopy (mustDeepCopy)dictdiggethasKeykeysmerge (mustMerge)mergeOverwrite (mustMergeOverwrite)omitpickplucksetunsetvalues

dict

建立字典是透過呼叫 dict 函數並傳遞一對清單來完成的。

以下建立一個包含三個項目的字典

$myDict := dict "name1" "value1" "name2" "value2" "name3" "value 3"

get

給定一個映射和一個鍵,從映射中取得值。

get $myDict "name1"

以上傳回 "value1"

請注意,如果找不到鍵,此操作將只傳回 ""。不會產生任何錯誤。

set

使用 set 將新的鍵/值對新增到字典中。

$_ := set $myDict "name4" "value4"

請注意,set *會傳回字典*(Go 範本函數的要求),因此您可能需要像上面使用 $_ 指派一樣擷取值。

unset

給定一個映射和一個鍵,從映射中刪除鍵。

$_ := unset $myDict "name4"

set 一樣,這會傳回字典。

請注意,如果找不到鍵,此操作將只傳回。不會產生任何錯誤。

hasKey

如果給定的字典包含給定的鍵,則 hasKey 函數會傳回 true

hasKey $myDict "name1"

如果找不到鍵,則傳回 false

pluck

pluck 函數可以提供一個鍵和多個映射,並取得所有符合項目的清單

pluck "name1" $myDict $myOtherDict

以上將傳回一個包含每個找到的值的 list[value1 otherValue1])。

如果在映射中*找不到*給定的鍵,則該映射在清單中將沒有項目(且傳回清單的長度將小於 pluck 呼叫中的字典數)。

如果*找到*鍵但值是空值,則會插入該值。

Helm 範本中的一個常見用法是使用 pluck... | first 從字典集合中取得第一個符合的鍵。

dig

dig 函數遍歷巢狀的字典集,從值清單中選擇鍵。如果在關聯的字典中找不到任何鍵,它會傳回預設值。

dig "user" "role" "humanName" "guest" $dict

給定一個結構如下的字典

{
  user: {
    role: {
      humanName: "curator"
    }
  }
}

以上將傳回 "curator"。如果字典甚至缺少 user 欄位,則結果將是 "guest"

在您想要避免防禦子句的情況下,Dig 非常有用,尤其是在 Go 的範本套件的 and 不會捷徑的情況下。例如,and a.maybeNil a.maybeNil.iNeedThis 將始終評估 a.maybeNil.iNeedThis,如果 a 缺少 maybeNil 欄位,則會發生恐慌。)

dig 接受其字典參數最後,以支援管道。例如

merge a b c | dig "one" "two" "three" "<missing>"

merge, mustMerge

將兩個或多個字典合併成一個,優先考慮目標字典

給定

dst:
  default: default
  overwrite: me
  key: true

src:
  overwrite: overwritten
  key: false

將導致

newdict:
  default: default
  overwrite: me
  key: true
$newdict := merge $dest $source1 $source2

這是一個深層合併操作,但不是深層複製操作。合併的巢狀物件在兩個字典上是相同的實例。如果您想要深層複製以及合併,則將 deepCopy 函數與合併一起使用。例如,

deepCopy $source | merge $dest

如果合併失敗,mustMerge 將傳回錯誤。

mergeOverwrite, mustMergeOverwrite

將兩個或多個字典合併成一個,優先順序從*右到左*,有效地覆蓋目標字典中的值

給定

dst:
  default: default
  overwrite: me
  key: true

src:
  overwrite: overwritten
  key: false

將導致

newdict:
  default: default
  overwrite: overwritten
  key: false
$newdict := mergeOverwrite $dest $source1 $source2

這是一個深層合併操作,但不是深層複製操作。合併的巢狀物件在兩個字典上是相同的實例。如果您想要深層複製以及合併,則將 deepCopy 函數與合併一起使用。例如,

deepCopy $source | mergeOverwrite $dest

如果合併失敗,mustMergeOverwrite 將傳回錯誤。

keys

keys 函數將傳回一個或多個 dict 類型中所有鍵的 list。由於字典是*無序的*,因此鍵的順序將無法預測。它們可以使用 sortAlpha 進行排序。

keys $myDict | sortAlpha

當提供多個字典時,鍵將被串連。將 uniq 函數與 sortAlpha 一起使用,以取得唯一、排序的鍵清單。

keys $myDict $myOtherDict | uniq | sortAlpha

pick

pick 函數只從字典中選擇給定的鍵,建立一個新的 dict

$new := pick $myDict "name1" "name2"

以上傳回 {name1: value1, name2: value2}

omit

omit 函數類似於 pick,不同之處在於它傳回一個新的 dict,其中包含所有*不*符合給定鍵的鍵。

$new := omit $myDict "name1" "name3"

以上傳回 {name2: value2}

values

values 函數類似於 keys,不同之處在於它傳回一個新的 list,其中包含來源 dict 的所有值(僅支援一個字典)。

$vals := values $myDict

以上傳回 list["value1", "value2", "value 3"]。請注意,values 函數不保證結果順序;如果您關心這個問題,則使用 sortAlpha

deepCopy, mustDeepCopy

deepCopymustDeepCopy 函數會取得一個值,並製作該值的深層副本。這包括字典和其他結構。當出現問題時,deepCopy 會發生恐慌,而 mustDeepCopy 會在出現錯誤時將錯誤傳回範本系統。

dict "a" 1 "b" 2 | deepCopy

關於字典內部的注意事項

dict 在 Go 中實作為 map[string]interface{}。Go 開發人員可以將 map[string]interface{} 值傳遞到上下文中,以使其作為 dict 可供範本使用。

編碼函數

Helm 具有以下編碼和解碼函數

  • b64enc/b64dec:使用 Base64 編碼或解碼
  • b32enc/b32dec:使用 Base32 編碼或解碼

清單和清單函數

Helm 提供了一個簡單的 list 類型,可以包含任意順序的資料清單。這類似於陣列或切片,但清單設計用於作為不可變的資料類型。

建立一個整數清單

$myList := list 1 2 3 4 5

以上程式碼會建立一個 [1 2 3 4 5] 的列表。

Helm 提供以下列表函數:append (mustAppend)compact (mustCompact)concatfirst (mustFirst)has (mustHas)initial (mustInitial)last (mustLast)prepend (mustPrepend)rest (mustRest)reverse (mustReverse)seqindexslice (mustSlice)uniq (mustUniq)untiluntilStepwithout (mustWithout)

first, mustFirst

要取得列表的第一個項目,請使用 first

first $myList 會回傳 1

如果發生問題,first 會發生 panic,而 mustFirst 會將錯誤回傳給模板引擎。

rest, mustRest

要取得列表的尾部(除了第一個項目以外的所有項目),請使用 rest

rest $myList 會回傳 [2 3 4 5]

如果發生問題,rest 會發生 panic,而 mustRest 會將錯誤回傳給模板引擎。

last, mustLast

要取得列表的最後一個項目,請使用 last

last $myList 會回傳 5。這大致類似於反轉列表,然後呼叫 first

initial, mustInitial

這與 last 互補,會回傳除了最後一個元素以外的所有元素。initial $myList 會回傳 [1 2 3 4]

如果發生問題,initial 會發生 panic,而 mustInitial 會將錯誤回傳給模板引擎。

append, mustAppend

將新項目附加到現有列表,建立新的列表。

$new = append $myList 6

以上程式碼會將 $new 設定為 [1 2 3 4 5 6]$myList 將保持不變。

如果發生問題,append 會發生 panic,而 mustAppend 會將錯誤回傳給模板引擎。

prepend, mustPrepend

將元素推送到列表的前面,建立新的列表。

prepend $myList 0

以上程式碼會產生 [0 1 2 3 4 5]$myList 將保持不變。

如果發生問題,prepend 會發生 panic,而 mustPrepend 會將錯誤回傳給模板引擎。

concat

將任意數量的列表串接成一個。

concat $myList ( list 6 7 ) ( list 8 )

以上程式碼會產生 [1 2 3 4 5 6 7 8]$myList 將保持不變。

reverse, mustReverse

產生一個新的列表,其中包含給定列表的反轉元素。

reverse $myList

以上程式碼會產生列表 [5 4 3 2 1]

如果發生問題,reverse 會發生 panic,而 mustReverse 會將錯誤回傳給模板引擎。

uniq, mustUniq

產生一個已移除所有重複項的列表。

list 1 1 1 2 | uniq

以上程式碼會產生 [1 2]

如果發生問題,uniq 會發生 panic,而 mustUniq 會將錯誤回傳給模板引擎。

without, mustWithout

without 函數會從列表中篩選掉項目。

without $myList 3

以上程式碼會產生 [1 2 4 5]

without 可以採用多個篩選器

without $myList 1 3 5

這會產生 [2 4]

如果發生問題,without 會發生 panic,而 mustWithout 會將錯誤回傳給模板引擎。

has, mustHas

測試列表是否具有特定元素。

has 4 $myList

以上程式碼會回傳 true,而 has "hello" $myList 會回傳 false。

如果發生問題,has 會發生 panic,而 mustHas 會將錯誤回傳給模板引擎。

compact, mustCompact

接受一個列表,並移除具有空值的項目。

$list := list 1 "a" "foo" ""
$copy := compact $list

compact 會回傳一個新的列表,其中已移除空的(即 "")項目。

如果發生問題,compact 會發生 panic,而 mustCompact 會將錯誤回傳給模板引擎。

index

要取得列表的第 n 個元素,請使用 index list [n]。要索引多維列表,請使用 index list [n] [m] ...

  • index $myList 0 會回傳 1。這與 myList[0] 相同
  • index $myList 0 1 會與 myList[0][1] 相同

slice, mustSlice

要取得列表的部分元素,請使用 slice list [n] [m]。這相當於 list[n:m]

  • slice $myList 會回傳 [1 2 3 4 5]。這與 myList[:] 相同。
  • slice $myList 3 會回傳 [4 5]。這與 myList[3:] 相同。
  • slice $myList 1 3 會回傳 [2 3]。這與 myList[1:3] 相同。
  • slice $myList 0 3 會回傳 [1 2 3]。這與 myList[:3] 相同。

如果發生問題,slice 會發生 panic,而 mustSlice 會將錯誤回傳給模板引擎。

until

until 函數會建立一個整數範圍。

until 5

以上程式碼會產生列表 [0, 1, 2, 3, 4]

這對於使用 range $i, $e := until 5 進行迴圈很有用。

untilStep

until 類似,untilStep 會產生一個計數整數列表。但它允許您定義起始值、結束值和步長

untilStep 3 6 2

以上程式碼會從 3 開始,並加上 2 直到等於或大於 6,從而產生 [3 5]。這類似於 Python 的 range 函數。

seq

作用類似於 bash 的 seq 命令。

  • 1 個參數(結束值) - 會產生 1 到 結束值 之間(含)的所有計數整數。
  • 2 個參數(起始值、結束值) - 會產生 起始值結束值 之間(含)的所有計數整數,以 1遞增或遞減。
  • 3 個參數(起始值、步長、結束值) - 會產生 起始值結束值 之間(含)的所有計數整數,以 步長 遞增或遞減。
seq 5       => 1 2 3 4 5
seq -3      => 1 0 -1 -2 -3
seq 0 2     => 0 1 2
seq 2 -2    => 2 1 0 -1 -2
seq 0 2 10  => 0 2 4 6 8 10
seq 0 -2 -5 => 0 -2 -4

數學函數

除非另有說明,否則所有數學函數都對 int64 值進行運算。

以下數學函數可用:addadd1ceildivfloorlenmaxminmodmulroundsub

add

使用 add 對數字求和。接受兩個或多個輸入。

add 1 2 3

add1

要遞增 1,請使用 add1

sub

要進行減法,請使用 sub

div

使用 div 執行整數除法。

mod

使用 mod 進行模數運算。

mul

使用 mul 進行乘法。接受兩個或多個輸入。

mul 1 2 3

max

回傳一系列整數中的最大值。

這會回傳 3

max 1 2 3

min

回傳一系列整數中的最小值。

min 1 2 3 會回傳 1

len

以整數形式回傳參數的長度。

len .Arg

浮點數數學函數

所有數學函數都對 float64 值進行運算。

addf

使用 addf 對數字求和

這會回傳 5.5

addf 1.5 2 2

add1f

要遞增 1,請使用 add1f

subf

要進行減法,請使用 subf

這相當於 7.5 - 2 - 3,並且會回傳 2.5

subf 7.5 2 3

divf

使用 divf 執行整數除法

這相當於 10 / 2 / 4,並且會回傳 1.25

divf 10 2 4

mulf

使用 mulf 進行乘法

這會回傳 6

mulf 1.5 2 2

maxf

回傳一系列浮點數中的最大值

這會回傳 3

maxf 1 2.5 3

minf

回傳一系列浮點數中的最小值。

這會回傳 1.5

minf 1.5 2 3

floor

回傳小於或等於輸入值的最大的浮點數值。

floor 123.9999 會回傳 123.0

ceil

回傳大於或等於輸入值的最大的浮點數值。

ceil 123.001 會回傳 124.0

round

回傳一個浮點數值,其餘數四捨五入到小數點後給定數量的位數。

round 123.555555 3 會回傳 123.556

網路函數

Helm 有一個網路函數,getHostByName

getHostByName 接收網域名稱,並回傳 IP 位址。

getHostByName "www.google.com" 會回傳 www.google.com 的對應 IP 位址。

檔案路徑函數

雖然 Helm 模板函數不允許存取檔案系統,但它們確實提供了用於處理遵循檔案路徑慣例的字串的函數。這些函數包括 basecleandirextisAbs

base

回傳路徑的最後一個元素。

base "foo/bar/baz"

以上程式碼會印出 "baz"。

dir

回傳目錄,去除路徑的最後一部分。因此 dir "foo/bar/baz" 會回傳 foo/bar

clean

清理路徑。

clean "foo/bar/../baz"

以上程式碼會解析 .. 並回傳 foo/baz

ext

回傳檔案副檔名。

ext "foo.bar"

以上程式碼會回傳 .bar

isAbs

要檢查檔案路徑是否為絕對路徑,請使用 isAbs

反射函數

Helm 提供基本的反射工具。這些工具可以幫助進階模板開發人員了解特定值的底層 Go 類型資訊。Helm 是用 Go 編寫的,並且是強類型的。類型系統適用於模板內。

Go 有幾種基本的*種類*,例如 stringsliceint64bool

Go 有一個開放的*類型*系統,允許開發人員建立自己的類型。

Helm 通過 種類函數類型函數 為每個種類和類型提供一組函數。還提供了一個 deepEqual 函數來比較兩個值。

種類函數

有兩個種類函數:kindOf 會回傳物件的種類。

kindOf "hello"

以上程式碼會回傳 string。對於簡單的測試(例如在 if 區塊中),kindIs 函數可以讓您驗證值是否為特定種類

kindIs "int" 123

以上程式碼會回傳 true

類型函數

類型稍微難以處理,因此有三個不同的函數

  • typeOf 會回傳值的底層類型:typeOf $foo
  • typeIs 類似於 kindIs,但適用於類型:typeIs "*io.Buffer" $myVal
  • typeIsLike 的作用與 typeIs 相同,但它還會取消指標的引用

**注意:**這些函數都無法測試某個東西是否實作了給定的介面,因為這樣做需要事先編譯介面。

deepEqual

如果兩個值 "深度相等",則 deepEqual 會回傳 true

也適用於非基本類型(與內建的 eq 相比)。

deepEqual (list 1 2 3) (list 1 2 3)

以上程式碼會回傳 true

語義版本函數

有些版本方案很容易解析和比較。Helm 提供了用於處理 SemVer 2 版本的函數。這些函數包括 semversemverCompare。您還可以在下面找到有關使用範圍進行比較的詳細資訊。

semver

semver 函數會將字串解析為語義版本

$version := semver "1.2.3-alpha.1+123"

如果解析失敗,它將導致模板執行停止並出現錯誤。

此時,$version 是一個指向具有以下屬性的 Version 物件的指標

  • $version.Major:主要版本號(以上為 1
  • $version.Minor:次要版本號(以上為 2
  • $version.Patch:修補版本號(以上為 3
  • $version.Prerelease:預發布版本(以上為 alpha.1
  • $version.Metadata:建置中繼資料(以上為 123
  • $version.Original:原始版本,以字串表示

此外,您可以使用 Compare 函數將 Version 與另一個 version 進行比較

semver "1.4.3" | (semver "1.2.3").Compare

以上程式碼會回傳 -1

回傳值如下

  • 如果給定的語意化版本大於呼叫其 `Compare` 方法的語意化版本,則傳回 `-1`
  • 如果呼叫 `Compare` 函數的版本較大,則傳回 `1`。
  • 如果它們是相同的版本,則傳回 `0`

(請注意,在語意化版本中,`Metadata` 欄位在版本比較操作期間不會被比較。)

semverCompare

一個更強大的比較函數以 `semverCompare` 的形式提供。此版本支援版本範圍

  • `semverCompare "1.2.3" "1.2.3"` 檢查是否完全匹配
  • `semverCompare "~1.2.0" "1.2.3"` 檢查主版本和次版本是否匹配,以及第二個版本的修訂號是否 *大於或等於* 第一個參數。

SemVer 函數使用 Sprig 的創建者所開發的 Masterminds semver 函式庫

基本比較

比較有兩個要素。首先,比較字串是由空格或逗號分隔的 AND 比較所組成的列表。然後這些比較會由 ||(OR)分隔。例如,`">= 1.2 < 3.0.0 || >= 4.2.3"` 正在尋找大於或等於 1.2 且小於 3.0.0 或大於或等於 4.2.3 的比較。

基本比較如下

  • `=`:等於(別名為無運算符)
  • `!=`:不等於
  • `>`:大於
  • `<`:小於
  • `>=`:大於或等於
  • `<=`:小於或等於

處理預發佈版本

預發佈版本,對於不熟悉的人來說,是用於穩定或正式發行版本之前的軟體發行版本。預發佈版本的例子包括開發版、Alpha 版、Beta 版和候選發行版。預發佈版本可能是 `1.2.3-beta.1` 之類的版本,而穩定版本則是 `1.2.3`。在優先順序上,預發佈版本排在其相關發行版本之前。在此範例中,`1.2.3-beta.1 < 1.2.3`。

根據語意化版本規範,預發佈版本可能與其發行版本不符合 API 規範。它指出:

預發佈版本表示該版本不穩定,並且可能不滿足其關聯的正式版本所表示的預期相容性要求。

使用沒有預發佈版本比較器的約束條件進行 SemVer 比較將會跳過預發佈版本。例如,`>=1.2.3` 在查看發行版本列表時將會跳過預發佈版本,而 `>=1.2.3-0` 將會評估並找到預發佈版本。

範例比較中使用 `0` 作為預發佈版本的原因是,根據規範,預發佈版本只能包含 ASCII 英數字和連字符(以及 `.` 分隔符號)。排序按照 ASCII 排序順序進行,同樣根據規範。在 ASCII 排序順序中,最低的字元是 `0`(請參閱 ASCII 表

了解 ASCII 排序順序很重要,因為 A-Z 排在 a-z 之前。這表示 `>=1.2.3-BETA` 將會傳回 `1.2.3-alpha`。您可能期望的大小寫敏感性在這裡不適用。這是由於 ASCII 排序順序是規範所指定的。

連字符範圍比較

有多種方法可以處理範圍,第一種是連字符範圍。它們看起來像這樣

  • `1.2 - 1.4.5` 等同於 `>= 1.2 <= 1.4.5`
  • `2.3.4 - 4.5` 等同於 `>= 2.3.4 <= 4.5`

比較中的萬用字元

`x`、`X` 和 `*` 字元可以用作萬用字元。這適用於所有比較運算符。當用於 `=` 運算符時,它會回到修訂號比較(請參閱下方的波浪號)。例如:

  • `1.2.x` 等同於 `>= 1.2.0, < 1.3.0`
  • `>= 1.2.x` 等同於 `>= 1.2.0`
  • `<= 2.x` 等同於 `< 3`
  • `*` 等同於 `>= 0.0.0`

波浪號範圍比較(修訂號)

波浪號 (`~`) 比較運算符用於指定次版本時的修訂號範圍,以及缺少次版本號時的主版本號變更。例如:

  • `~1.2.3` 等同於 `>= 1.2.3, < 1.3.0`
  • `~1` 等同於 `>= 1, < 2`
  • `~2.3` 等同於 `>= 2.3, < 2.4`
  • `~1.2.x` 等同於 `>= 1.2.0, < 1.3.0`
  • `~1.x` 等同於 `>= 1, < 2`

插入符號範圍比較(主版本號)

插入符號 (`^`) 比較運算符用於在穩定版(1.0.0)發行之後的主版本號變更。在 1.0.0 版本之前,次版本號充當 API 穩定性級別。這在比較 API 版本時很有用,因為主版本號變更會破壞 API。例如:

  • `^1.2.3` 等同於 `>= 1.2.3, < 2.0.0`
  • `^1.2.x` 等同於 `>= 1.2.0, < 2.0.0`
  • `^2.3` 等同於 `>= 2.3, < 3`
  • `^2.x` 等同於 `>= 2.0.0, < 3`
  • `^0.2.3` 等同於 `>=0.2.3 <0.3.0`
  • `^0.2` 等同於 `>=0.2.0 <0.3.0`
  • `^0.0.3` 等同於 `>=0.0.3 <0.0.4`
  • `^0.0` 等同於 `>=0.0.0 <0.1.0`
  • `^0` 等同於 `>=0.0.0 <1.0.0`

URL 函數

Helm 包括 urlParseurlJoinurlquery 函數,讓您可以處理 URL 部分。

urlParse

解析字串中的 URL 並產生包含 URL 部分的字典

urlParse "http://admin:secret@server.com:8080/api?list=false#anchor"

以上傳回一個字典,包含 URL 物件

scheme:   'http'
host:     'server.com:8080'
path:     '/api'
query:    'list=false'
opaque:   nil
fragment: 'anchor'
userinfo: 'admin:secret'

這是使用 Go 標準函式庫中的 URL 套件實作的。如需更多資訊,請查看 https://go.dev.org.tw/pkg/net/url/#URL

urlJoin

合併地圖(由 `urlParse` 產生)以產生 URL 字串

urlJoin (dict "fragment" "fragment" "host" "host:80" "path" "/path" "query" "query" "scheme" "http")

以上傳回以下字串

http://host:80/path?query#fragment

urlquery

傳回作為參數傳入的值的跳脫版本,以便適合嵌入 URL 的查詢部分。

$var := urlquery "string for query"

UUID 函數

Helm 可以產生 UUID v4 通用唯一 ID。

uuidv4

以上傳回一個新的 v4 類型(隨機產生)的 UUID。

Kubernetes 和 Chart 函數

Helm 包括用於處理 Kubernetes 的函數,包括 .Capabilities.APIVersions.Has檔案lookup

lookup

`lookup` 用於在正在執行的叢集中查找資源。與 `helm template` 命令一起使用時,它總是傳回空的回應。

您可以在 lookup 函數的說明文件中 找到更多詳細資訊。

.Capabilities.APIVersions.Has

傳回叢集中是否可以使用 API 版本或資源。

.Capabilities.APIVersions.Has "apps/v1"
.Capabilities.APIVersions.Has "apps/v1/Deployment"

更多資訊可在 內建物件說明文件 中找到。

檔案函數

有幾個函數讓您可以存取 Chart 中的非特殊檔案。例如,存取應用程式設定檔。這些函數在 存取範本中的檔案 中有說明。

請注意,其中許多函數的說明文件來自 Sprig。Sprig 是一個 Go 應用程式可用的範本函數庫。