20

I want to format float64 value to 2 decimal places in golang html/template say in index.html file. In .go file I can format like:

strconv.FormatFloat(value, 'f', 2, 32)

But I don't know how to format it in template. I am using gin-gonic/gin framework for backend. Any help will be appreciated. Thanks.

Bhavana
  • 1,014
  • 4
  • 17
  • 26

4 Answers4

36

You have many options:

  • You may decide to format the number e.g. using fmt.Sprintf() before passing it to the template execution (n1)
  • Or you may create your own type where you define the String() string method, formatting to your liking. This is checked and used by the template engine (n2).
  • You may also call printf directly and explicitly from the template and use custom format string (n3).
  • Even though you can call printf directly, this requires to pass the format string. If you don't want to do this every time, you can register a custom function doing just that (n4)

See this example:

type MyFloat float64

func (mf MyFloat) String() string {
    return fmt.Sprintf("%.2f", float64(mf))
}

func main() {
    t := template.Must(template.New("").Funcs(template.FuncMap{
        "MyFormat": func(f float64) string { return fmt.Sprintf("%.2f", f) },
    }).Parse(templ))
    m := map[string]interface{}{
        "n0": 3.1415,
        "n1": fmt.Sprintf("%.2f", 3.1415),
        "n2": MyFloat(3.1415),
        "n3": 3.1415,
        "n4": 3.1415,
    }
    if err := t.Execute(os.Stdout, m); err != nil {
        fmt.Println(err)
    }
}

const templ = `
Number:         n0 = {{.n0}}
Formatted:      n1 = {{.n1}}
Custom type:    n2 = {{.n2}}
Calling printf: n3 = {{printf "%.2f" .n3}}
MyFormat:       n4 = {{MyFormat .n4}}`

Output (try it on the Go Playground):

Number:         n0 = 3.1415
Formatted:      n1 = 3.14
Custom type:    n2 = 3.14
Calling printf: n3 = 3.14
MyFormat:       n4 = 3.14
icza
  • 389,944
  • 63
  • 907
  • 827
  • Thanks for the help. But how can I format in template itself? Is there any way to format? Or I have to pass custom type too to the template with other data? Please help. – Bhavana Dec 15 '16 at 08:45
  • @user29 See the `n4` case: a "pure" number of type `float64` is passed (`3.1415`), and it is formatted in the tempalte: `{{printf "%.2f" .n4}}`. – icza Dec 15 '16 at 08:47
  • 1
    5th option: use a sub-template: `{{define "FloatFmt"}}{{printf "%.2f" .}}{{end}}` and use it with `{{template "FloatFmt"}}`. You have to wrap the call with a `{{with}}` block if the value is not `.`: `{{with .n0}}{{template "FloatFmt"}}{{end}}`). – dolmen Feb 01 '17 at 13:54
  • 2
    @dolmen Good tip. About the `{{template}}` action: `{{template "name"}}` executes the template with `nil` data, but you can pass any data to it, e.g. `{{template "name" .n0}}`, so no need to wrap with `{{with}}`. Although, I think executing another template has worse performance than just calling a function. – icza Feb 01 '17 at 14:07
15

Use the printf template built-in function with the "%.2f" format:

tmpl := template.Must(template.New("test").Parse(`The formatted value is = {{printf "%.2f" .}}`))

tmpl.Execute(os.Stdout, 123.456789)

Go Playgroung

dolmen
  • 8,126
  • 5
  • 40
  • 42
4

You can register a FuncMap.

package main

import (
    "fmt"
    "os"
    "text/template"
)

type Tpl struct {
    Value float64
}

func main() {
    funcMap := template.FuncMap{
        "FormatNumber": func(value float64) string {
            return fmt.Sprintf("%.2f", value)
        },
    }

    tmpl, _ := template.New("test").Funcs(funcMap).Parse(string("The formatted value is = {{ .Value | FormatNumber  }}"))

    tmpl.Execute(os.Stdout, Tpl{Value: 123.45678})
}

Playground

Nadh
  • 6,987
  • 2
  • 21
  • 21
1

Edit: I was wrong about rounding/truncating.

The problem with %.2f formatting is that it does not round but truncates.

I've developed a decimal class based on int64 for handling money that is handling floats, string parsing, JSON, etc.

It stores amount as 64 bit integer number of cents. Can be easily created from float or converted back to float.

Handy for storing in DB as well.

https://github.com/strongo/decimal

package example

import "github.com/strongo/decimal"

func Example() {
    var amount decimal.Decimal64p2; print(amount)  // 0

    amount = decimal.NewDecimal64p2(0, 43); print(amount)  // 0.43
    amount = decimal.NewDecimal64p2(1, 43); print(amount)  // 1.43
    amount = decimal.NewDecimal64p2FromFloat64(23.100001); print(amount)  // 23.10
    amount, _ = decimal.ParseDecimal64p2("2.34"); print(amount)  // 2.34
    amount, _ = decimal.ParseDecimal64p2("-3.42"); print(amount)  // -3.42
}

Works well for my debts tracker app https://debtstracker.io/

Alexander Trakhimenok
  • 6,019
  • 2
  • 27
  • 52