Sign In
Sign In

How to Use Templates in Go

How to Use Templates in Go
Hostman Team
Technical writer
Go
05.12.2024
Reading time: 13 min

Go (Golang) comes with a powerful, versatile templating system that allows for dynamic output generation, whether it's textual information (such as an email, document, or simply a console command) or entire web pages.

Template processing in Go is based on two primary packages, each serving its own purpose:

  • text/template
  • html/template

It’s important to note that both packages have an identical interface; however, the second (html/template) automatically protects HTML output from certain types of attacks, such as injections.

Converting a Go template into final output is done by applying the template to the appropriate data structure. The input text for Go templates can be in any format and encoded in UTF-8.

Template Entities

A template is generally associated with a specific data structure (e.g., a struct) whose data will be inserted into the template.

Thus, any template formally consists of three basic types of entities that "extract" the necessary variables and insert them into the output:

  1. Actions
    These are text fragments enclosed in curly braces {{ }}, where calculations or data substitutions take place. Actions make the content within the template dynamic by inserting the appropriate data. Actions can include simple variable substitutions, as well as loops or function executions that contribute to the final output. They directly control how the final result will appear.

  2. Conditions
    Conditions are the classic if-else constructions used within the template. Conditions allow you to include or exclude entire blocks of text from the final output, significantly enhancing the flexibility and capability of template-based content generation.

  3. Loops
    Loops allow you to iterate over a collection of data, outputting multiple similar blocks but with different key information. These are useful when you need to generate repeated elements based on a list or array.

Managing Templates in Go

In Go, there are three most commonly used functions for managing templates:

  1. New: Creates a new template, which must be defined later.

  2. Parse: Analyzes the provided string containing the template text, and then returns a ready-to-use template.

  3. Execute: Executes the parsed template, applying the provided data structure, and writes the result to a specified variable.

Additionally, there is the ParseFiles function, which allows you to process entire files containing the template's content rather than just a string.

The following code demonstrates how to use these basic template functions in a simple scenario:

package main

// In addition to the template package, we import "os", which provides a platform-independent interface for interacting with the operating system. In this case, we'll use it to output the result of the template execution to the console.

import (
    "os"
    "text/template"
)

// Define a struct whose data will be inserted into the template.

type Person struct {
    Name string
    Age  int
}

func main() {
    some_person := Person{"Alex", 32} // Instance of the previously defined struct
    some_template := "This is {{ .Name }} and he is {{ .Age }} years old" // Template text with embedded actions inside curly braces

    // Create a new template and parse its content, preparing it for further use
    ready_template, err := template.New("test").Parse(some_template)

    // Check for errors (nil means no error, similar to null in C)
    if err != nil {
        panic(err) // Stop execution and print the error
    }

    // Execute the template and print the result to the console
    err = ready_template.Execute(os.Stdout, some_person) // OUTPUT: This is Alex and he is 32 years old

    // Check for errors again
    if err != nil {
        panic(err) // Stop execution and print the error
    }
}

You can reuse a template "compiled" using the Parse function but with data from a different structure. For example, you could continue the main function from the above code like this:

// Continuing from the previous code

...

    another_person := Person{"Max", 27} // Create another instance of the struct
    err = ready_template.Execute(os.Stdout, another_person)
}

In this case, the template will be reused and applied to the new instance (another_person), producing different output based on the new data.

Note that inside a template, variables from the structure that was passed during execution are referenced within double curly braces {{ }}. When referring to these variables, the structure name is implicitly omitted and only the variable name is used, prefixed with a dot.

For example:

This is {{ .Name }} and he is {{ .Age }} years old

You can also directly access the data passed during execution. For instance, the following code demonstrates how to pass simple text directly into the template:

package main

import (
   "os"
   "text/template"
)

func main() {
    some_template := "Here we have {{ . }}"
    ready_template, err := template.New("test").Parse(some_template)

    if err != nil { 
        panic(err) 
    }

    ready_template.Execute(os.Stdout, "no data, only text") // OUTPUT: Here we have no data, only text
}

In this example, the template simply inserts whatever value was passed to it (in this case, "no data, only text") without referencing a structure or fields within a structure.

Template Syntax Features

Static Text

In the simplest case, a template can simply output static text without using any additional data:

import (
    "os"
    "text/template"
)

...

some_template := "Just regular text"
ready_template, err := template.New("test").Parse(some_template)

if err != nil { panic(err) }

ready_template.Execute(os.Stdout, "no data") // OUTPUT: Just regular text

Static Text Inside Actions (Curly Braces)

You can combine regular static text with additional data within curly braces:

import (
    "os"
    "text/template"
)

...

some_template := "Not just regular text with {{ \"additional\" }} data" // Don't forget to escape the double quotes
ready_template, err := template.New("test").Parse(some_template)

if err != nil { panic(err) }

ready_template.Execute(os.Stdout, "no data") // OUTPUT: Not just regular text with additional data

Trimming Whitespace Markers

You can use trimming markers before and after the curly braces to remove spaces:

...

some_template := "Not just regular text with {{- \"additional\" -}} data"

...

ready_template.Execute(os.Stdout, "no data") // OUTPUT: Not just regular text withadditionaldata

// The output above isn't a typo — the spaces around "additional" have been removed

Trimming markers remove not only a single space but multiple spaces on both sides of the text produced by the code inside the curly braces — both from the inside and outside.

Numbers in Templates

Unlike text, numbers are automatically inserted into the output without needing quotes:

...

some_template := "Maybe this code was written by {{ 5 }} people."

...

ready_template.Execute(os.Stdout, "no data") // OUTPUT: Maybe this code was written by 5 people.

Similarly, trimming markers can be used with numbers as well:

...

some_template := "Maybe this code was written by {{- 5 }} people."

...

ready_template.Execute(os.Stdout, "no data") // OUTPUT: Maybe this code was written by5 people.

Template Variables

Golang allows you to define special variables that are only available within the template itself. Like in Go, a variable is defined by specifying its name and value, and then it is used. To define an internal variable, use $:

package main

import (
    "os"
    "text/template"
)

func main() {
    some_template := "First, we define a variable {{- $some_variable :=`Hello, I'm a variable` }}, then we use it: \"{{ $some_variable }}\""
    ready_template, err := template.New("test").Parse(some_template)

    if err != nil { panic(err) }

    ready_template.Execute(os.Stdout, "no data") // OUTPUT: First, we define a variable, then we use it: "Hello, I'm a variable"
}

Note that to access the variable, we use $ because this variable is not related to any Go data structure, but is defined within the template itself.

Conditional Expressions

Go templates allow branching based on logic using the standard if/else conditional operators found in most programming languages:

package main

import (
    "os"
    "text/template"
)

func main() {
    some_template := "{{ if eq . `hello` -}} Hello! {{ else -}} Goodbye! {{ end }}" // We use a trimming marker after each condition to remove the leading space in the output
    ready_template, err := template.New("test").Parse(some_template)

    if err != nil { panic(err) }

    ready_template.Execute(os.Stdout, "hello") // OUTPUT: Hello!
}

In this example, the eq function is used (which stands for "equal") to compare the value passed to the template (accessed via the dot) with the string hello.

Also, note that every conditional block is terminated with the end keyword.

You can actually simplify the code by skipping the string comparison and directly passing a boolean variable, which makes the code more concise:

package main

import (
    "os"
    "text/template"
)

func main() {
    some_template := "{{ if . -}} Hello! {{ else -}} Goodbye! {{ end }}"
    ready_template, err := template.New("test").Parse(some_template)

    if err != nil { panic(err) }

    ready_template.Execute(os.Stdout, false) // OUTPUT: Goodbye!
}

Loops

Templates are commonly used to output multiple similar data items, where the number of items changes from one output to another. This is where loops come in handy:

package main

import (
    "os"
    "text/template"
)

func main() {
    some_list := []string{"First", "Second", "Third"}
    some_template := "Let's count in order: {{ range .}}{{.}}, {{ end }}"
    ready_template, err := template.New("test").Parse(some_template)

    if err != nil { panic(err) }

    ready_template.Execute(os.Stdout, some_list) // OUTPUT: Let's count in order: First, Second, Third,
}

In this example, there's one issue—the last item in the list results in an extra comma followed by a space. To fix this, you can modify the code to check if the item is the last one in the list, ensuring that there is no comma and space after the last item:

package main

import (
    "os"
    "text/template"
)

func main() {
    some_list := []string{"First", "Second", "Third"}
    some_template := "Let's count in order: {{ range $index, $element := .}}{{ if $index }}, {{ end }}{{$element}}{{ end }}"
    ready_template, err := template.New("test").Parse(some_template)

    if err != nil { panic(err) }

    ready_template.Execute(os.Stdout, some_list) // OUTPUT: Let's count in order: First, Second, Third
}

In this modified example, two new variables are introduced—$index and $element—which are updated on each iteration of the loop. A comma and space are printed before each element, but only if the index ($index) is not zero. This ensures that the comma is not added before the first element.

Template Functions

Within Go templates, you can define and call custom functions that perform various operations on the passed arguments. However, before using them in a template, they need to be explicitly declared and registered.

Here is an example:

package main

import (
    "os"
    "text/template"
)

func manipulate(first_arg, second_arg int) int { 
    return first_arg + second_arg
} 

func main() {
    some_list := []int{1, 2, 3}
    some_template := "Adding index and element in order: {{ range $index, $element := .}}{{ if $index }}, {{ end }}{{$index}} + {{$element}} = {{ do_manipulation $index $element }}{{ end }}"
    ready_template, err := template.New("test").Funcs(template.FuncMap{"do_manipulation": manipulate}).Parse(some_template)

    if err != nil { panic(err) }

    ready_template.Execute(os.Stdout, some_list) // OUTPUT: Adding index and element in order: 0 + 1 = 1, 1 + 2 = 3, 2 + 3 = 5
}

In this example, we intentionally renamed the Go function manipulate inside the template to do_manipulation. This is possible due to Go's flexibility. However, you could also use the original function name by simply registering it like this:

ready_template, err := template.New("test").Funcs(template.FuncMap{"manipulate": manipulate}).Parse(some_template)

This allows the custom function manipulate (or do_manipulation if renamed) to be used within the template for performing operations like addition on the index and element.

Working with HTML Templates in Go

As mentioned earlier, Go has an additional package for working with HTML templates: html/template. Unlike the standard text/template, this package protects applications from cross-site scripting (XSS) attacks, as Go ensures that data is safely rendered without allowing malicious content.

Here’s how to import the necessary packages:

import (
    "html/template"
    "net/http"
)

The net/http package is required to start an HTTP server on your local machine, which is necessary for testing the next example.

HTML Template File

It's best practice to store the template in a separate file. In this case, we'll create a file with the .html extension, although you can use any extension you prefer in your projects — Go does not impose any restrictions.

We'll call the file index.html:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Document</title>
</head>
<body>
   <h1>{{ .Title }}</h1>
   <p> {{ .Text }} </p>
</body>
</html>

Notice that we’ve specified two variables: Title and Text. Their values will be passed from a Go structure into the template.

Minimal Go Code to Serve HTML Template

Now let’s write the minimal Go code to run an HTTP server and send the rendered template result as a response to any request to the server:

package main

import (
    "os"
    "html/template"
    "net/http"
    "log"
)

// Declare the structure to store data for generating the template
type Content struct {
    Title string
    Text  string
}

// Function to handle HTTP requests to the server
func generateResponse(writer http.ResponseWriter, request *http.Request) {
    if request.Method == "GET" {
        some_template, _ := template.ParseFiles("index.html") // Parse the template file
        some_content := Content{
            Title: "This is the Title",
            Text:  "This is the text content",
        }

        err := some_template.Execute(writer, some_content) // Execute the template, writing the output to the response writer

        if err != nil {
            panic(err)
        }
    }
}

func main() {
    // Start the HTTP server and use the generateResponse function to handle requests
    http.HandleFunc("/", generateResponse)
    err := http.ListenAndServe("localhost:8080", nil)

    if err != nil {
        log.Fatalln("Something went wrong:", err)
    }
}

Conclusion

The Go programming language provides built-in support for creating dynamic content or rendering customizable output through templates. On our app platform you can deploy Golang apps, such as Beego and Gin. 

This article covered the basic template functions that allow you to manage data dynamically, altering it according to a defined pattern — the template description itself.

The implementation involves a few usage options:

  • text/template

  • html/template

Remember that every template goes through three stages of formation, each of which is handled by a corresponding function:

  • New: Creating the template.

  • Parse: Analyzing (parsing) the template.

  • Execute: Executing the template. This stage can be repeated indefinitely.

You can refer to the official Go documentation on the text/template and html/template packages for more detailed information on the available functions and ways to use them.

Go
05.12.2024
Reading time: 13 min

Similar

Go

For Loops in the Go Programming Language

A loop is a block of code that runs until a specified condition is met or a required number of repetitions is completed. Loops are convenient for solving tasks where a program needs to repeat the same actions multiple times. For example, imagine you have a list of directors. You need to extract each director's last name and display it on the screen. Instead of manually accessing each element of the list, it's easier to use a loop. A loop will iterate through the list and display each last name on the screen. Loops in Go In Go, there are only for loops. There are no while or do while loops like in some other languages. Similar concepts are implemented using the same for loop. This design choice makes the code more readable. Developers don't have to decide on a looping strategy — if you need to repeat actions, there's for, which can be used in various ways. Let's explore how to create loops in Golang to solve specific tasks. ForClause The structure of a ForClause is simple. It consists of a condition and a body. The code inside the body executes if the condition is evaluated as true. for i := 0; i < 6; i++ { fmt.Println(i) } Here: i := 0 is the initializer. It sets the starting value of the loop. i < 6 is the condition. If it is evaluated as true, the code inside the loop is executed. fmt.Println(i) sequentially prints numbers from 0 to 5. i++ is the post-operation that increments i by 1 after each iteration. The code starts with i = 0. Since 0 < 6, the condition is true, and 0 is printed. Then, i++ increments i by 1, making i = 1. The loop continues as long as i < 6. When i becomes 6, the condition i < 6 is false, and the loop stops. The number 6 is not printed. Output: 0 1 2 3 4 5 You don't have to start at zero or stop at a fixed value. The for loop in Go allows you to adjust the logic as needed. for i := 100; i < 150; i = i + 10 { fmt.Println(i) } Output: 100 110 120 130 140 If you modify the condition slightly, you can include the number 150: for i := 100; i <= 150; i = i + 10 { fmt.Println(i) } Output: 100 110 120 130 140 150 You can also iterate in reverse, from the end to the beginning, by modifying the condition and the post-operation. for i := 50; i > 0; i -= 10 { fmt.Println(i) } Here, the loop starts with i = 50. On each iteration, it checks if i > 0. If the condition is true, it subtracts 10 from the current value of i. Output: 50 40 30 20 10 Note that 0 is not printed because the condition requires i > 0. Loop with a Condition If you remove the initializer and post-operator from the syntax, you get a simple construct that works based on a condition. The loop declaration in this case looks like this: i := 0 for i < 6 { fmt.Println(i) i++ } If you are familiar with other programming languages, you might recognize this as similar to a while loop. In this example, i is defined outside the loop. The for loop only has a condition, which keeps the loop running while i is less than 6. Note that the increment operation (i++), previously specified as a post-operator, is now inside the body. Sometimes, the number of iterations is unknown in advance. You can't specify a condition for ending the loop in such cases. To avoid infinite loops, Go supports the break keyword. Here's a simple example: func main() { i := 0 for { fmt.Println("Hello") if i == 5 { break } i++ } } Initially, i = 0. The loop runs indefinitely, printing "Hello" each time. However, when i reaches 5, the break statement is executed, and the program stops. RangeClause Go also provides another type of loop — the RangeClause. It is similar to ForClause, but it returns two values by default: the index of an element and its value. package main import "fmt" func main() { words := []string{"host", "man", "hostman", "cloud"} for i, word := range words { fmt.Println(i, word) } } Output: 0 host 1 man 2 hostman 3 cloud To omit the index, use an underscore _ as a placeholder: package main import "fmt" func main() { words := []string{"host", "man", "hostman", "cloud"} for _, word := range words { fmt.Println(word) } } Output: host man hostman cloud You can also use range to add elements to a list: package main import "fmt" func main() { words := []string{"host", "man", "hostman", "cloud"} for range words { words = append(words, "great") } fmt.Printf("%q\n", words) } Output: ["host" "man" "hostman" "cloud" "great" "great" "great" "great"] In this example, the word "great" is added for each element in the original length of the words slice. Suppose you have a slice of 10 zeros and need to populate it with numbers from 0 to 9: package main import "fmt" func main() { integers := make([]int, 10) fmt.Println(integers) for i := range integers { integers[i] = i } fmt.Println(integers) } [0 0 0 0 0 0 0 0 0 0] [0 1 2 3 4 5 6 7 8 9] You can use range to iterate over each character in a string: package main import "fmt" func main() { hostman := "Hostman" for _, letter := range hostman { fmt.Printf("%c\n", letter) } } Output: H o s t m a n This allows you to process each character in a string individually. Nested Constructs A for loop can be created inside another construct, making it nested. We can represent its syntax as: for { [Action] for { [Action] } } First, the outer loop starts running. It executes and then triggers the inner loop. After the inner loop finishes, the program returns to the outer loop. This process repeats as long as the given condition holds or until the program encounters a break statement. There is also a risk of creating an infinite loop, which even the powerful resources of Hostman wouldn’t handle, as the program would never terminate. To avoid this, always ensure the condition is properly checked or use the break operator. Here’s a simple example to demonstrate nested loops: package main import "fmt" func main() { numList := []int{1, 2} alphaList := []string{"a", "b", "c"} for _, i := range numList { fmt.Println(i) for _, letter := range alphaList { fmt.Println(letter) } } } Output: 1 a b c 2 a b c This example clearly demonstrates the order of operations: The first value from numList (1) is printed. The inner loop executes, printing each value from alphaList (a, b, c). The program returns to the outer loop and prints the next value from numList (2). The inner loop runs again, printing the values of alphaList (a, b, c) a second time. Conclusion Using for loops in Go is straightforward. Depending on the task, you can choose one of the three main forms of for or combine them to create nested constructs. You can control the loop's behavior by modifying the condition, initializer, and post-operator or by using break and continue statements. Nested loops provide flexibility and power but should be used carefully to avoid infinite loops or excessive computational overhead. You can deploy Go applications (such as Beego and Gin) on our app platform.
11 December 2024 · 6 min to read
Go

How to Install Go on Windows

Go, or Golang, is a high-performance, multithreaded programming language developed by Google in 2007 and released in 2009. To this day, Golang continues to gain popularity.  The Go programming language supports many operating systems, making it a versatile choice for development across various platforms. In this guide, we will walk through the step-by-step process of installing Golang on Windows. Installing Go on Windows Go supports Windows 7 and newer versions. Ensure that you have a supported version of the OS installed. In this guide, we will use Windows 11. You will also need an administrator account to configure environment variables. To install Golang on Windows: Download the installer for the latest version of Microsoft Windows from the official Go website. If needed, you can select any other available version of the language instead of the latest one. Once the file has finished downloading, run it and follow the installation wizard's instructions. If necessary, you can change the file location. This will be useful when configuring environment variables. After the installation, check if Golang was successfully installed on your system. To do this, open the terminal (Win + R → cmd) and run the following command: go version The output should show the version of Go you just installed. For example: To update Golang to a newer version on Windows, you must uninstall the old version and follow the instructions to install the new one. Now, let's move on to setting up environment variables so that Go works properly. Setting Up Environment Variables Setting up environment variables is an important step in installing Go on Windows, as it allows the operating system to determine where the necessary Go files and directories are located. For Go to work correctly, two environment variables are required: GOPATH points to where Go stores downloaded and compiled packages. PATH allows the system to find Go executable files without specifying their full paths. GOPATH First, let's set up the GOPATH environment variable. For this, you need to organize a workspace where Go files and projects will be stored. In this guide, we will create a workspace at C:\GoProject. We will also add two directories to this folder: bin – for storing executable files (binary files). Go creates an executable file and places it in this directory when you compile your project. src – for storing Go source files. All .go files will be placed here. After creating the workspace, we will set the GOPATH environment variable. To do this, go to the Control Panel → System and Security → System and click on Advanced System Settings. There is also an easier way to access system properties: open the Run window (Win + R) and enter: sysdm.cpl Click on Environment Variables, then click the New button under the User Variables section. Here, you need to fill in two fields: the variable name and its value. In the Variable name field, enter GOPATH, and in the Variable value field, enter the path to the workspace you created earlier (in our case, C:\GoProject). Click OK twice to save the changes. To verify the creation of the system variable, open the Run window (Win + R) and enter the string: %GOPATH% If everything was done correctly, your workspace will open. PATH The PATH environment variable should have been automatically added after we installed Go. To check this, go to the Control Panel → System and Security → System and click on Advanced System Settings. In the window that opens, you need to find PATH among the system variables. To view its values, double-click on it. In the new window, there should be an entry that holds the path to the Go bin folder. In our case, it is C:\Program Files\Go\bin. If your value does not match what was specified during the Go installation, change it to the correct one using the Edit button. At this point, the installation of Golang on Windows and the setup of environment variables is complete. Now we can check its functionality by writing and running our first program. Verifying Installation To check the functionality of the newly installed Golang on Windows: Сreate a test file with the .go extension in the workspace (C:\GoProject\src). For example, ExampleProgram.go. Add the following simple code: package mainimport "fmt"func main() {    fmt.Println("Hello, Go has been successfully installed into your system!")} The program should display a message confirming that Go has been successfully installed on your system. To compile and run the program, enter the following command in the terminal: go run %GOPATH%/src/ExampleProgram.go As shown in the image below, the program compiles and runs, displaying the specified text on the screen. Conclusion Installing Go on Windows is a straightforward process, involving downloading the installer, setting up environment variables, and verifying the installation. Once Go is properly configured, you can easily start developing applications. With support for multiple operating systems, Go remains a powerful and versatile language, ideal for cross-platform development. On our app platform you can deploy Golang apps, such as Beego and Gin. 
10 December 2024 · 5 min to read
Go

Type Conversion in Go

Go is a statically typed programming language, meaning that data types are tied to variables. If you declare a variable as int to store numerical values, you cannot store a string in it. This rule works in the reverse direction as well. Static typing protects developers from errors where the program expects one data type and gets another. However, this strict binding can be limiting when performing certain operations. Go provides type conversion (or type casting) to overcome this limitation. This formal process allows developers to convert integer values to floating-point numbers, strings to numbers, and vice versa. This article will help you understand how to perform such conversions. Data Types in Go The basic types in Go are as follows: bool — Boolean values: true or false string — Strings int, int8, int16, int32, int64 — Signed integer types uint, uint8, uint16, uint32, uint64, uintptr — Unsigned integer types byte — Alias for uint8 rune — Alias for int32 float32, float64 — Floating-point numbers complex64, complex128 — Complex numbers The types int, uint, and uintptr have a width of 32 bits in 32-bit systems and 64 bits in 64-bit systems. When you need an integer value, you should use int unless you have a specific reason for using a sized or unsigned integer type. Go does not have a char data type. The language uses byte and rune to represent character values. byte represents ASCII characters, while rune represents a broader set of Unicode characters encoded in UTF-8. To define characters in Go, you enclose them in single quotes like this: 'a'. The default type for character values is rune. If you do not explicitly declare the type when assigning a character value, Go will infer the type as rune: var firstLetter = 'A' // Type inferred as `rune` You can explicitly declare a byte variable like this: var lastLetter byte = 'Z' Both byte and rune are integer types. For example, a byte with the value 'a' is converted to the integer 97. Similarly, a rune with the Unicode value '♥' is converted to the corresponding Unicode code point U+2665, where U+ indicates Unicode, and the numbers are in hexadecimal, which is essentially an integer. Here's an example: package main import "fmt" func main() { var myByte byte = 'a' var myRune rune = '♥' fmt.Printf("%c = %d and %c = %U\n", myByte, myByte, myRune, myRune) } Output: a = 97 and ♥ = U+2665 When you need to convert from int to string or vice versa, you essentially take the type initially assigned to a variable and convert it to another type. As mentioned earlier, Go strictly formalizes these actions. The examples in this article will help you understand the basics of such conversions. Number Conversion in Go Converting numeric types can be useful when solving various tasks. For example, we decided to add a calculator to the website. It should perform only one operation: division. The main requirement is that the result be accurate down to the last digit. However, when dividing two integer variables, the result may be inaccurate. For example: package main import "fmt" func main() { var first int = 15 var second int = 6 var result = first / second fmt.Println(result) } Output: 2 After executing this code, you get 2. The program outputs the nearest integer quotient, but this is far from the precise division you need. Such a calculator is not useful. To improve the accuracy, you need to cast both variables to float. Here's how you can do it: package main import "fmt" func main() { var first int = 15 var second int = 6 var result = float64(first) / float64(second) fmt.Println(result) } Output: 2.5 Now the output will be precise — 2.5. It was quite easy to achieve by simply wrapping the variables with the float64() or float32() conversion functions. Now the calculator works as expected. Product metrics are not a concern, as the feature is technically implemented correctly. You can also divide numbers without explicitly converting them to float. When you use floating-point numbers, other types are automatically cast to float. Try this code: package main import "fmt" func main() { a := 5.0 / 2 fmt.Println(a) } Output: 2.5 Even though you didn’t explicitly use the float64() or float32() wrapper in the code, Go's compiler automatically recognizes that 5.0 is a floating-point number and performs the division with the floating-point precision. The result is displayed as a floating-point number. In the first example with division, you explicitly cast the integers to float using the float64() function. Here’s another example of converting from int64 to float64: package main import "fmt" func main() { var x int64 = 57 var y float64 = float64(x) fmt.Printf("%.2f\n", y) } Output: 57.00 The two zeros after the decimal point appear because we added the %.2f\n format specifier. Instead of 2, you could specify any other number, depending on how many decimal places you want to display. You can also convert from float to int. Here's an example: package main import "fmt" func main() { var f float64 = 409.8 var i int = int(f) fmt.Printf("f = %.3f\n", f) fmt.Printf("i = %d\n", i) } Output: f = 409.800i = 409 In this example, the program prints f = 409.800 with three decimal places. In the second print statement, the float is first converted to int, and the decimal part is discarded. Note that Go does not perform rounding, so the result is 409 without any rounding to the nearest integer. Strings Conversion in Go In Golang, we can convert a number to a string using the method strconv.Itoa. This method is part of the strconv package in the language's standard library. Run this code: package main import ( "fmt" "strconv" ) func main() { a := strconv.Itoa(12) fmt.Printf("%q\n", a) } The result should be the string "12". The quotes in the output indicate that this is no longer a number. In practice, such string-to-number and number-to-string conversions are often used to display useful information to users. For example, if you're building an online store, you can host it at Hostman, implement the core business logic, and fill it with products. After some time, the product manager suggests improving the user profile. The user should see the amount they have spent and how much more they need to spend to reach the next level. To do this, you need to display a message in the user profile that consists of a simple text and a set of digits. Try running this code: package main import ( "fmt" ) func main() { user := "Alex" sum := 50 fmt.Println("Congratulations, " + user + "! You have already spent " + lines + " dollars.") } The result will be an error message. You cannot concatenate a string and a number. The solution to this problem is to convert the data in Go. Let's fix the code by converting the variable lines to a string: package main import ( "fmt" "strconv" ) func main() { user := "Alex" sum := 50 fmt.Println("Congratulations, " + user + "! You have already spent " + strconv.Itoa(sum) + " dollars.") } Now, there will be no error, and the output will display the correct message with the proper set of digits. Of course, this is a simplified example. In real projects, the logic is much more complex and challenging. However, knowing the basic operations helps avoid a large number of errors. This is especially important when working with complex systems. Let's go back to our example. The product manager comes again and says that customers want to see the exact total amount of their purchases in their profile, down to the pennies. An integer value won't work here. As you already understood from the examples above, all digits after the decimal point are simply discarded. To make sure the total purchase amount in the user profile is displayed correctly, we will convert not an int, but a float to a string. For this task, there is a method fmt.Sprint, which is part of the fmt package. package main import ( "fmt" ) func main() { fmt.Println(fmt.Sprint(421.034)) f := 5524.53 fmt.Println(fmt.Sprint(f)) } To verify that the conversion was successful, concatenate the total with the string. For example: package main import ( "fmt" ) func main() { f := 5524.53 fmt.Println("Alex spent " + fmt.Sprint(f) + " dollars.") } There is no error now, and the information message correctly displays the floating-point number. Customers can see how much money they've spent in your store, with all expenses accounted for down to the penny. A common reverse task is to convert a string into numbers. For example, you have a form where the user enters their age or any other numeric values. The entered data is saved in the string format. Let's try working with this data— for instance, performing a subtraction: package main import ( "fmt" ) func main() { lines_yesterday := "50" lines_today := "108" lines_more := lines_today - lines_yesterday fmt.Println(lines_more) } The result of running this code will be an error message, as subtraction cannot be applied to string values. To perform mathematical operations on data stored as strings, you need to convert them to int or float. The choice of method depends on the type you will convert the string to. If you are working with integers, use the strconv.Atoi method. For floating-point numbers, use the strconv.ParseFloat method. package main import ( "fmt" "log" "strconv" ) func main() { lines_yesterday := "50" lines_today := "108" yesterday, err := strconv.Atoi(lines_yesterday) if err != nil { log.Fatal(err) } today, err := strconv.Atoi(lines_today) if err != nil { log.Fatal(err) } lines_more := today - yesterday fmt.Println(lines_more) } In this example, you use the if operator to check whether the conversion was successful. If an error occurs, the program will terminate, and the error information will be saved in the log. If the conversion is successful, the output will give you the correct result: 108 - 50 = 58. If you try to convert a string that does not contain a numerical value in the same way, you will receive an error message: strconv.Atoi: parsing "not a number": invalid syntax Try running this code: package main import ( "fmt" "strconv" ) func main() { a := "not a number" b, err := strconv.Atoi(a) fmt.Println(b) fmt.Println(err) } The code from the example above will fail because you are trying to convert a string whose value is not a number into a numeric type. Strings can also be converted to byte slices and back using the []byte() and string() constructs.  package main import ( "fmt" ) func main() { a := "hostman" b := []byte(a) c := string(b) fmt.Println(a) fmt.Println(b) fmt.Println(c) } In this function, you save the string to variable a, then convert the same string into a byte slice and save it to variable b, then turn the byte slice into a string and save the result to variable c. The output will be like this: hostman[104 111 115 116 109 97 110]hostman This simple example shows that you can easily convert strings to byte slices and back. Conclusion In this article, we only covered the basics. We looked at the available data types and how to perform type conversion in Go. If you want to learn more, explore the language documentation or at least the "A Tour of Go" tutorial — it's an interactive introduction to Go divided into three sections. The first section covers basic syntax and data structures, the second discusses methods and interfaces, and the third introduces Go's concurrency primitives. Each section concludes with several exercises so you can practice what you've learned.  In addition,  you can deploy Go applications (such as Beego and Gin) on our app platform.
10 December 2024 · 10 min to read

Do you have questions,
comments, or concerns?

Our professionals are available to assist you at any moment,
whether you need help or are just unsure of where to start.
Email us
Hostman's Support