Type Conversion in Go

Type Conversion in Go

#GO-getter series

Why type conversion?

The process of software development is all about handling the user input before persisting it into the database and more often than not, such a situation arises when receiving data does not conform to the type of data we are handling. In computing, the robustness principle is a design guideline for software that states: "be conservative in what you do, be liberal in what you accept from others". It is often reworded as: "be conservative in what you send, be liberal in what you accept". The principle is also known as Postel's law, after Jon Postel, who used the wording in an early specification of TCP.(refer to Robustness principle for more information)

In other words, programs that send messages to other machines (or to other programs on the same machine) should conform completely to the specifications, but programs that receive messages should accept non-conformant input as long as the meaning is clear. To abide by this design guideline, every programming language has a way to convert the type of data to a specified type provided explicitly or implicitly.

Go vs Other

Assigning a value of one data type to another data type is called a type conversion. Type conversion Wikipedia page says:

Languages like C, CPP and Java perform automatic type conversion or implicit type conversion between the compatible data types according to their language specification. For example in Java, implicit type conversion happens between the numeric data types where the value of the smaller data type can be automatically promoted to the bigger data type by declaring the data type to which it needs to convert as shown below.

public class firstClass{
    public static void main(String[] args) {

        int a = 5;

        float b = a;

        System.out.println(b);

    }
}

At the time of initializing a, data type was int. By merely assigning a to float type b converts a into float. Java compiler implicitly performs the type conversion and changes the data type of a from int to float. But Golang is different, as it doesn’t support the Implicit Type Conversion even if the data types are compatible. Implicit Type Conversion lead to the ambiguity and loss of precision being the main reasons why it is not implemented in Go language.

Type Conversion

In Go, there is nothing like type casting and type coercion. If one searches for such words in Go language specification, he or she won't find them. There is only type conversion. Golang type conversion specification states that a conversion changes the type of an expression to the type specified by the conversion. A conversion may appear literally in the source, or it may be implied by the context in which an expression appears. An explicit conversion is an expression of the form T(x) where T is a type and x is an expression that can be converted to type T.

Write the below Go code into your favorite IDE and run:

package main

import "fmt"

func main() {

    var num1 int = 65
    fmt.Printf("Type of num1 is %T\n", num1)
    fmt.Printf("Value of num1 is %v\n", num1)

    var num2 float32 = num1
    fmt.Printf("Type of num2 is %T\n", num2)
    fmt.Printf("Value of num2 is %v\n", num2)

}

The program will encounter an error saying cannot use num1 (variable of type int) as float32 value in variable declaration. Now it is evident that implicit conversion is not allowed in Golang. Let's modify the above code as per the Golang specs and see what happens.

Write down the above code with minor modifications by explicitly informing the Go compiler about the data type of the num1 that is being assigned to num2.

package main

import "fmt"

func main() {

    var num1 int = 65
    fmt.Printf("Type of num1 is %T\n", num1)
    fmt.Printf("Value of num1 is %v\n", num1)

    var num2 float32 = float32 (num1)

    fmt.Printf("Type of num2 is %T\n", num2)
    fmt.Printf("Value of num2 is %v\n", num2)

}

Now, the error is vanished and it will compile successfully. num1 of type int is being converted to type of float32. In the same way, all the numeric data type conversions can be handled.

Handling string in type conversion

Regardless of the language, string data type is by far the most used data type in the web development. Know-how related to the conversions to and from a string type is a must while learning any programming language.

Consider the following example as the data coming from the API in the form of string.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    welcome := "Welcome to the SMS feedback system"
    fmt.Println(welcome)

    fmt.Println("Please share a rating on scale of 1 to 5. 1 being the least satisfied and 5 being the most satisfied")
    reader := bufio.NewReader(os.Stdin)

    input, _ := reader.ReadString('\n')
    fmt.Printf("Type of the input is %T\n", input)

}

Despite user input of type int, data type of input is string since ReadString() function of the bufio package reads until the first occurrence of delim in the input, returning a string containing the data up to and including the delimiter. Suppose you might want to use input, and add some value to it before sending it to other function. Try to add some value to input using the explicit type conversion shown below.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    welcome := "Welcome to the SMS feedback system"
    fmt.Println(welcome)

    fmt.Println("Please share a rating on scale of 1 to 5. 1 being the least satisfied and 5 being the most satisfied")
    reader := bufio.NewReader(os.Stdin)

    input, _ := reader.ReadString('\n')
    fmt.Printf("Type of the input is %T\n", input)

    var a int = int (input) + 1

    fmt.Println("Value of a is %v",a)

}

Running this code will throw the compile error saying cannot convert input (variable of type string) to type int compiler (InvalidConversion). To overcome this error, we have to use the Go strconv package that implements conversions to and from string representations of basic data types as described below.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    welcome := "Welcome to the SMS feedback system"
    fmt.Println(welcome)

    fmt.Println("Please share a rating on scale of 1 to 5. 1 being the least satisfied and 5 being the most satisfied")
    reader := bufio.NewReader(os.Stdin)

    input, _ := reader.ReadString('\n')
    fmt.Printf("Type of the input is %T\n", input)

    number, err := strconv.ParseFloat(strings.TrimSpace(input), 64)

    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("Thank you for rating: ", number)
    }

    var a int = int (number) + 1
    fmt.Printf("Value of a is %v\n",a)

}

As per the Go documentation, ParseFloat converts the string s to a floating-point number with the precision specified by bitSize: 32 for float32, or 64 for float64. When bitSize=32, the result still has type float64, but it will be convertible to float32 without changing its value. Hit the URL https://pkg.go.dev/ , get into the Go packages, search for strconv and see the implementation of func ParseFloat. It accepts two arguments first being the string and second being the int which is an integer that specifies the precision or size of the floating-point number to be returned.

input consists of the string with a trailing delim which is a new line character that needs to be trimmed from the string before setting it as an argument. func TrimSpace from the strings returns a slice of the string s, with all leading and trailing white space removed, as defined by Unicode. A new line character or any whitespace not being removed before setting it as an argument will cause an error floating strconv.ParseFloat: parsing "input\n": invalid syntax where input is the data being converted.

strconv.ParseFloat() returns converted string into float64 or float32 and errors that have concrete type *NumError and include err.Num = s. If s is not syntactically well-formed, ParseFloat returns err.Err = ErrSyntax. If the conversion is successful, number will contain the floating-point number, and err will be nil. If there is an error during the conversion, err will contain information about the error, and number will be set to its zero value.

After converting string into the data type we want, we can further use it for the manipulation. In our case, we are incrementing it by 1.

Packages strings and strconv which are one of the most used in Go provides different functionalities to handle string in a varied way. You can refer to it and learn alternative ways to handle the string. Happy Learning.