次のようにするにはどうすればよいですか。
{{ $use_ssl := (ne $.Env.CERT_NAME "") }}
ここで、$.Env.CERT_NAME
はnil /未定義の場合があります。 nilの場合、次のエラーが発生します。
at <ne $.Env.CERT_NAME "">: error calling ne: invalid type for comparison
注:Goテンプレートに渡されるオブジェクトを制御することはできないため、テンプレート自体の中でこれを完全に解決する必要があります。
私はそれが空でないかどうかを最初にチェックすることで回避しようとしました:
{{ $use_ssl := ( ($.Env.CERT_NAME) && (ne $.Env.CERT_NAME "") ) }}
しかし、それはこのエラーを出します:
unexpected "&" in operand
だから私はこれに切り替えました、これは構文的に許可されています:
{{ $use_ssl := (and ($.Env.CERT_NAME) (ne $.Env.CERT_NAME "") ) }}
しかし、私は&&
演算子で取得する 短絡評価 を失い、再びこのエラーを取得します。
at <ne $.Env.CERT_NAME ...>: error calling ne: invalid type for comparison
わかりました、いいワンライナーでそれを実行できない場合、そして Goに三項演算子がない 、それは問題ありません、私はそれをやります 慣用的なGo way 、明らかにif/else
です。
{{ if $.Env.CERT_NAME }}
{{ $use_ssl := (ne $.Env.CERT_NAME "") }}
{{ else }}
{{ $use_ssl := false }}
{{ end }}
しかしもちろん、スコーピングの問題が発生します。if
が不可解に(または少なくとも厄介なことに)新しい変数スコープを作成するため(慣れているRuby/ERBテンプレートとは異なります)、明らかにできません。これも行う:
{{ if $.Env.CERT_NAME }}
{{ $use_ssl := true }}
{{ else }}
{{ $use_ssl := false }}
{{ end }}
# $use_ssl: {{ $use_ssl }}
このエラーが発生することなく:
undefined variable "$use_ssl"
「汗はない」と思った。外部スコープで変数を宣言するだけなので、正しいスコープを持ち、内部スコープはその変数を変更できます( 1つは外側のスコープ)。 (ちなみに、これがRubyでの動作方法です。)
いいえ、どうやっても、同じ名前でスコープが異なる2つの異なる変数を作成するだけです(混乱を招く方法は次のとおりです)。
{{ $use_ssl := false }}
{{ if $.Env.CERT_NAME }}
{{ $use_ssl := true }}
# $use_ssl: {{ $use_ssl }}
{{ else }}
{{ $use_ssl := false }}
{{ end }}
# $use_ssl: {{ $use_ssl }}
# $use_ssl: true
# $use_ssl: false
また、次のようなifステートメントをインライン化してみました。
{{ $use_ssl := if $.Env.CERT_NAME { true } }}
しかし、それはこのエラーを与えます:
unexpected <if> in command
どうやらif
ステートメントは、RubyのようにGoの式として使用できないのですか?
で提案されている三項演算子のさまざまな代替手段を試した場合も、構文エラーが発生します。Cの三項演算子に相当する慣用的なGoとは何ですか 。
c := map[bool]int{true: 1, false: 0} [5 > 4]
そして確かに、あなたは$.something
で内部スコープの外部スコープから変数を読み取ることができますが、どのようにしてください set$.something
は内部スコープにありますか?
それで私は何を逃したのですか?これはGoテンプレートでも可能ですか?
Goテンプレート(私はそれらに慣れていない)は非常に制限されているようです。 Go自体でできるほとんどすべてのことは、テンプレートでは不可能です。しかし、うまくいけば回避策があります...
http://play.golang.org/p/SufZdsx-1v には、{{$hasFemale := cell false}}
で新しいオブジェクトを作成し、$hasFemale.Set true
ですが、テンプレートを評価するコード(template.FuncMap
を呼び出しているコード)にアクセスせずに、どうすればこのようなことができますか?
https://groups.google.com/forum/#!topic/golang-nuts/MUzNZ9dbHrg
これがGoで私が抱えている最大の(そして唯一の)問題です。この機能がまだ実装されていない理由がわかりません。
テンプレートパッケージが一般的なコンテキストで使用される場合(たとえば、任意のテンプレートファイルを任意のjsonファイルで実行するなど)、事前計算を行う余裕がない場合があります。
https://github.com/golang/go/issues/10608
これはおそらく設計されたとおりですが、変更された$ vを条件外で取得する方法があった場合、それは本当にすばらしいでしょう。
これは、Hugo( https://github.com/spf13/hugo )で私たちが乗り越えるテンプレートの質問の1つ目です。 hack [
$.Scratch.Set "v1" 123
]を追加して、今のところそれを回避します...
set
を使用するかmerge
を使用して、変数を宣言するのではなくスコープを更新すると、if句の外からアクセスできるようになります。
{{- if eq .podKind "core" -}}
{{- $dummy := set . "matchNodePurpose" .Values.scheduling.corePods.nodeAffinity.matchNodePurpose }}
{{- else if eq .podKind "user" -}}
{{- $dummy := set . "matchNodePurpose" .Values.scheduling.userPods.nodeAffinity.matchNodePurpose }}
{{- end -}}
# Will now output what you decided within an if/else if clause
{{- .matchNodePurpose }}
Sprig などのいくつかの追加機能がプリインストールされたgoテンプレートであるHelmテンプレートのコンテキストで同じ質問に遭遇しました。
2018年3月28日、このprで TerenaryオペレーターがSprigに追加され、Helmはそのうちにあなたと私が抱えている問題を解決するようになります。
terenary
true | ternary "b" "c"
戻ります "b"
false | ternary "b" "c"
戻ります "c"
特定の問題の回避策を見つけたと思いますが、問題をより一般的に解決する他の回答を聞きたいです。
https://github.com/jwilder/nginx-proxy/blob/1e0b930/nginx.tmpl#L91 :
{{ $default_Host := or ($.Env.DEFAULT_Host) "" }}
試してみる別のアイデアが得られました。解決策はor
の組み合わせを使用し、追加の一時変数を設定することだと思います...
{{ $cert_name := or $.Env.CERT_NAME "" }}
{{ $use_ssl := ne $cert_name "" }}