summaryrefslogtreecommitdiffstats
path: root/docs/content/en/functions/go-template/try.md
blob: f3385a04c6039be8e3f61e0df7ed31bab7ba9f31 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
---
title: try
description: Returns a TryValue object after evaluating the given expression.
categories: []
keywords: []
action:
  aliases: []
  related: []
  returnType: TryValue
  signatures: ['try EXPRESSION']
toc: true
---

{{< new-in 0.141.0 />}}

The `try` statement is a non-standard extension to Go's [text/template] package. It introduces a mechanism for handling errors within templates, mimicking the `try-catch` constructs found in other programming languages.

[text/template]: https://pkg.go.dev/text/template

## Methods

The `TryValue` object encapsulates the result of evaluating the expression, and provides two methods:

Err
: (`string`) Returns a string representation of the error thrown by the expression, if an error occurred, or returns `nil` if the expression evaluated without errors.

Value
: (`any`) Returns the result of the expression if the evaluation was successful, or returns `nil` if an error occurred while evaluating the expression.

## Explanation

By way of example, let's divide a number by zero:

```go-html-template
{{ $x := 1 }}
{{ $y := 0 }}
{{ $result := div $x $y }}
{{ printf "%v divided by %v equals %v" $x $y .Value }}
```

As expected, the example above throws an error and fails the build:

```terminfo
Error: error calling div: can't divide the value by 0
```

Instead of failing the build, we can catch the error and emit a warning:

```go-html-template
{{ $x := 1 }}
{{ $y := 0 }}
{{ with try (div $x $y) }}
  {{ with .Err }}
    {{ warnf "%s" . }}
  {{ else }}
    {{ printf "%v divided by %v equals %v" $x $y .Value }}
  {{ end }}
{{ end }}
```

The error thrown by the expression is logged to the console as a warning:

```terminfo
WARN error calling div: can't divide the value by 0
```

Now let's change the arguments to avoid dividing by zero:

```go-html-template
{{ $x := 42 }}
{{ $y := 6 }}
{{ with try (div $x $y) }}
  {{ with .Err }}
    {{ warnf "%s" . }}
  {{ else }}
    {{ printf "%v divided by %v equals %v" $x $y .Value }}
  {{ end }}
{{ end }}
```

Hugo renders the above to:

```html
42 divided by 6 equals 7
```

## Example

Error handling is essential when using the [`resources.GetRemote`] function to capture remote resources such as data or images. When calling this function, if the HTTP request fails, Hugo will fail the build.

[`resources.GetRemote`]: /functions/resources/getremote/

Instead of failing the build, we can catch the error and emit a warning:

```go-html-template
{{ $url := "https://broken-example.org/images/a.jpg" }}
{{ with try (resources.GetRemote $url) }}
  {{ with .Err }}
    {{ warnf "%s" . }}
  {{ else with .Value }}
    <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
  {{ else }}
    {{ warnf "Unable to get remote resource %q" $url }}
  {{ end }}
{{ end }}
```
In the above, note that the [context](g) within the last conditional block is the `TryValue` object returned by the `try` statement. At this point neither the `Err` nor `Value` methods returned anything, so the current context is not useful. Use the `$` to access the [template context] if needed.

[template context]: /templates/introduction/#template-context

{{% note %}}
Hugo does not classify an HTTP response with status code 404 as an error. In this case `resources.GetRemote` returns nil.
{{% /note %}}