Right, comments. The part of the template where you talk to yourself, to future you, or to the poor soul who has to maintain your code after you’ve been promoted away from this mess. In a language where logic and presentation are smashed together, comments aren’t just nice-to-have; they’re a survival tool. Let’s be honest, the Go template syntax can get… gnarly. A well-placed comment is a beacon of clarity in a storm of curly braces and dot notations.

Go templates give you two flavours of comments, and your choice depends entirely on whether you want the comment to be visible in the final rendered HTML.

The Invisible Workhorse: {{/* ... */}}

This is your standard, run-of-the-mill, “this is for developers only” comment. The template parser completely strips it out before rendering. Nothing inside these braces will ever see the light of day in a user’s browser. This is where you explain your weird logic, call out a hack, or leave a note for your successor.

{{/* Fetch the latest 5 blog posts for the sidebar. */}}
{{ $sidebarPosts := where .Site.RegularPages "Type" "post" | first 5 }}

{{/*
  This next bit is a hack because the 'author' front matter is sometimes
  an array and sometimes a string. Blame past me. I didn't know better.
  TODO: Standardize this in the content files.
*/}}
{{ $author := default "Anonymous" (index .Params.author 0) }}

Use these liberally. Future you will send past you a mental thank-you note.

The Visible Aside: <!-- {{ ... }} -->

Now, this one is a bit of a parlor trick. You’re using a standard HTML comment <!-- -->, but you’re putting Go template logic inside it. The template engine will execute whatever is inside the braces, but the result will be wrapped in HTML comment tags.

Why would you ever do this? Debugging. It’s brilliantly stupid and stupidly brilliant.

<!-- {{ printf "Rendering single.html for page: %s" .Title }} -->
<article>
  <h1>{{ .Title }}</h1>
  <!-- {{ with .Params.hero_image }} 
       Found a hero image: {{ . }}
       {{ end }} -->
  {{ .Content }}
</article>
<!-- {{ printf "Rendered at %s" now }} -->

When you’re building a complex template and something isn’t rendering right, you can drop these in to see the values of variables at runtime without littering your actual page with debug text. Just remember to remove them before going to production, unless you want to give your users a peek behind the curtain at your internal variables. (Spoiler: You don’t.)

The Pitfall: Comments and White Space

Ah, here’s where our “helpful” template designers decided to get clever. Go templates are notoriously opinionated about white space. By default, including a comment will affect the white space in your output. Notice the newlines in the example above? They’ll be rendered.

Sometimes you don’t want that. To tell the template engine to strip the white space surrounding a comment, you need to use the dash modifiers inside the braces, just like with any other action.

{{- /* This comment will not create a newline before or after it */ -}}
<p>First paragraph.</p>
{{- /* This one neither */ -}}
<p>Second paragraph.</p>

Without those dashes, you’d have newlines between your paragraphs. It’s a small thing, but it can matter immensely for inline elements or minified HTML. Always ask yourself: “Do I care about the space this comment might generate?” If the answer is no, don’t worry about it. If the answer is yes, get chummy with the -.

Best Practice: Comment for Intent, Not Action

This is the golden rule. Don’t just comment what the code is doing; comment why it’s doing it. The code itself shows the action. Your job is to provide the context that the syntax can’t.

Bad:

{{ $posts := where .Site.Pages "Type" "post" }} {{/* Get posts */}}

Good:

{{/* We use 'RegularPages' instead of 'Pages' to exclude section pages and other non-content nodes from this list */}}
{{ $posts := where .Site.RegularPages "Type" "post" }}

The first comment is useless noise. The second explains a non-obvious but critical design decision. That’s the stuff that saves hours of head-scratching. Comment like the person who reads it next knows less than you do, but is smarter. Because that person is probably you, in six months, after you’ve forgotten everything about this project.