Is there a Go switch-case syntax that can be used in Hugo templates and shortcodes in place of multiple if-else conditions?
In Hugo there is also with
that is more terse.
I’m new to Hugo and Go in general, but I’m not sure with
is exactly what I want: I want my shortcode to behave differently depending on a value of a shortcode parameter that can have several alternative values, and there are instances where I also want to configure a default behavior. If I understand your intention correctly, using with
I can write something like this:
{{ $type := .Get 0 }}
{{ with (eq $type "A") }}
...
{ end }}
{{ with (eq $type "B") }}
...
{{ end }}
...
That works but it’s not exactly a switch case like in other languages, and I’m not sure it’s simpler or cleaner than using multiple if
-else
clauses. The advantage of if
-else
compared to this with
implementation is that (a) The processing will stop when any of the conditions evaluates to true, which is more efficient. (b) It inherently supports a default-behavior alternative, while with
would require additional code for that. Or am I missing something here?
Thanks
From the docs:
with
An alternative way of writing “if” and then referencing the same value is to use “with” instead. with rebinds the context . within its scope, and skips the block if the variable is absent.
In my opinion it’s much cleaner than writing multiple if/else
or isset
statements.
You can read more regarding Hugo conditionals over here: Templating | Hugo
EDIT
Regarding default behaviour Hugo has a pipeline for that. See here: Functions | Hugo
In Go templates there are if
, if else
and else
, but no switch
.
-
Regarding the
with
documentation that you quoted from the Hugo docs, I have actually already read it but I don’t think it addresses the issues with usingwith
for my specific use case. Assuming the parameter that I’m evaluating always exists, unlike switch-case syntax in other languages, I would still need to repeat the condition code for testing its value in eachwith
clause (similar toif
/else
clauses), and end each clause with{{ end }}
; and all thewith
clauses will be evaluated while withif
-else
the evaluation will stop when a match is found.Is my
with
example what you meant, or did you have anotherwith
construct in mind? -
Thanks for pointing out the
default
function. That’s useful.
Your example is what I had in mind. But @bep has already answered that there is no switch
in Go.
So I guess you have to make do with what’s available.
OK, thanks guys. Now I’ve run into another problem, which is probably related to my basic Hugo/Go ignorance:I tried using the code below to implement what I want, but the $id
and $title
variables are always evaluated to their initialization values (in this case, empty strings, but I tested using non-empty strings as well). I verified (using debug prints) that the relevant with
clause is applied according to the value of the shortcode’s 0
parameter. However, the reassignments of the $id
and $title
variables in the with
clauses (or outside of them) is not applied. I also wasn’t able to define these variables without initializing their values. I’m guessing there’s an error in my variable definition and/or assignment syntax, but I can’t figure it out. Perhaps you can point me in the right direction?
{{ $type := .Get 0 }}
{{ $id := "" }}
{{ $title := "" }}
{{ with (eq $type "new") }}
{{ $id := "new-features" }}
{{ $title := "New Features" }}
{{ end }}
{{ with (eq $type "enhancements") }}
{{ $id := "enhance" }}
{{ $title := "Enhancements" }}
{{ end }}
{{ with (eq $type "fix") }}
{{ $id := "fixes" }}
{{ $title := "Fixes" }}
{{ end }}
<a id="{{ $id }}"></a>
<h2>{{ $title }}</h2>
They’re empty because you’re not populating them with the variables.
Do this instead
{{ $id := .Get "id" }} {{ $title := .Get "title" }}
I assume that you have corresponding title
and id
parameters in your shortcode.
I don’t have $id
and $title
shortcode parameters. These are local variables that I define in the shortcode. Therefore the .Get
code that you suggested won’t work, as it’s suited for getting parameter values. I’m assuming there should be a way to define local shortcode variables and update their values conditionally, shouldn’t there?
How are you defining them? Show us an example.
You can also get them by position like you’re getting type
.
I copied the full code in my previous message; the definition is in the second and third lines.
The initial assignment works, because I tested using non-empty strings in the definition and if I print the variable values the initialization strings are printed. The issue is that the reassignment to these variables (inside or outside of my with
clauses) has no effect.
I meant an example of how you’re calling the shortcode in a content file with the variables defined. Not the shortcode itself.
But you should also bear in mind that shortcodes are rendered from the inside then out in Hugo.
I’m calling the shortcode like this: {{< release-notes-heading "new" >}}
; (I also tested with %
instead of <
/>
, although the shortcode doesn’t include Markdown code). But why does the shortcode-call syntax matter when when the issue is with local variables? The parameter that I’m passing to the shortcode is evaluated correctly.
I’m not sure what you mean by this?
So “new” is a variable correct? If yes, you should be able to get it by position using .Get 1
See this for an explanation: Explanation of rendering order
No. new
is a value of the unnamed 0
parameter, which I assign to a $type
variable using .Get 0
. Based on the value of this parameter, I want to create an HTML heading with specific text and ID, which I set differently depending on the value of the unnamed 0
parameter (e.g., “new”). Instead of repeating the heading + anchor HTML in each with
clause but with a different text and anchor ID (as I currently do), I want to use local $id and $title variables, and then write the HTML code once, at the end, using the local variables to set the appropriate text and title (see my code).
Thanks for this link. It definitely seems useful, but I don’t think it helps with my current issue, as there is no nesting or other template calls involved.
Right. The following syntax is untested but it should work for you.
{{ $type := .Get 0 }} {{ with (eq $type "new") }}<a id="new-features"></a><h2>New Features</h2>{{ end }} {{ with (eq $type "enhancements") }}<a id="enhance"></a><h2>Enhancements</h2>{{ end }} {{ with (eq $type "fix") }}<a id="fixes"></a><h2>Fixes</h2>{{ end }}