Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Go Data Types Explained

Tech May 16 3

Go is a statically typed programming language. In Go, data types are used to declare functions and variables. Data types categorize data based on the memory size required. When programming, you request larger memory only when you need large data, thus making efficient use of memory. During compilation, the compiler needs to know the type of each value so it can determine how much memory to allocate for that value and what the allocated memory represents.

![Go data types overview diagram]

Basic Data Types Overview

Type Description
uint 32-bit or 64-bit
uint8 Unsigned 8-bit integer (0 to 255)
uint16 Unsigned 16-bit integer (0 to 65535)
uint32 Unsigned 32-bit integer (0 to 4294967295)
uint64 Unsigned 64-bit integer (0 to 18446744073709551615)
int 32-bit or 64-bit
int8 Signed 8-bit integer (-128 to 127)
int16 Signed 16-bit integer (-32768 to 32767)
int32 Signed 32-bit integer (-2147483648 to 2147483647)
int64 Signed 64-bit integer (-9223372036854775808 to 9223372036854775807)
byte Alias for uint8 (type byte = uint8)
rune Alias for int32 (type rune = int32), represents a Unicode code point
uintptr Unsigned integer type large enough to hold a pointer. Used in low-level programming, especially when interfacing with C libraries or the OS.
float32 IEEE-754 32-bit floating-point number
float64 IEEE-754 64-bit floating-point number
complex64 32-bit real and imaginary parts
complex128 64-bit real and imaginary parts

Integers

Integers are divided into two categories: signed and unsigned.

Signed: int, int8, int16, int32, int64

Unsigned: uint, uint8, uint16, uint32, uint64, byte

The difference between integer types of different bit sizes is the range of numbers they can hold.

Signed types can store any integer, while unsigned types can only store non-negative integers.

The size of int and uint depends on the system: on a 32-bit system they represent int32 and uint32, on a 64-bit system they represent int64 and uint64.

byte is similar to uint8 and is generally used to store a single character.

To ensure program correctness, try to use data types that occupy as little memory as possible.

Use fmt.Printf("%T", varName) to output the type of a variable.

Use unsafe.Sizeof(varName) to check the byte size occupied by a variable.

Floating-Point Numbers

Floating-point numbers are decimal types that can store fractional values like 6.6 or -12.34.

  1. Storage of floats: In machine representation, a float consists of a sign bit, exponent bits, and mantissa bits.

  2. Precision loss: The mantissa may lose precision. For example:

package main

import "fmt"

func main() {
    var num1 float32 = -123.0000901
    var num2 float64 = -123.0000901
    fmt.Println("num1 = ", num1, "num2 = ", num2)
}

![output showing precision difference]

float64 offers higher precision than float32. For high-precision numbers, choose float64.

  1. Float storage consists of three parts: sign bit, exponent bits, and mantissa bits, which may cause precision loss during storage.

  2. Go's default floating-point type is float64.

  3. Generally, use float64 as it is more precise than float32.

  4. 0.123 can be written as .123. Scientific notation is also supported: 5.1234e2 equals 512.34.

Characters

Go does not have a dedicated character type. To store a single character (like a letter), use byte.

A string is a sequence of fixed-length characters. Go strings are composed of individual bytes. Unlike traditional strings composed of characters, Go strings are made of bytes.

  • Characters must be enclosed in single quotes ('), not double quotes. Double quotes are for strings.
  • When directly outputting a byte variable, its ASCII code value is printed.
  • To output the character itself, use formatted output with %c.
  • Go uses UTF-8 encoding. English letters occupy 1 byte, while Chinese characters occupy 3 bytes.
  • In Go, a character is essentially an integer. Direct output gives the UTF-8 code point.
  • You can assign a numeric value to a variable and output it with %c to get the corresponding Unicode character.
  • Character types support arithmetic because they have corresponding Unicode code points.
package main

import "fmt"

func main() {
    var c1 byte = 'a'
    var c2 byte = '0'

    // Direct output prints ASCII value
    fmt.Println(c1, "--", c2)

    // Formatted output prints the character
    fmt.Printf("c1 = %c c2 = %c", c1, c2)
}

![output of character code example]

However, to store characters larger than 255 (e.g., Chinese characters), byte is insuffficient. Use uint or int types instead.

Character Type Essence

  1. Storing a character in a computer requires finding its corresponding code point (integer).

    • Storage: Character → Code point → Binary → Stored
    • Retrieval: Binary → Code point → Character → Displayed
  2. The relationship between characters and code points is defined by a character encoding table (standardized).

  3. Go uses UTF-8 encoding uniformly, eliminating charset confusion.

Boolean Type

The boolean type (bool) can only take values true or false.

bool occupies 1 byte.

Boolean values are used in logical operations and typically for flow control.

Strings

A string is a sequence of fixed-length characters. Go strings are composed of individual bytes and use UTF-8 encoding to represent Unicode text.

  1. Immutability: Once a string is assigned, it cannot be modified. Strings in Go are immutable.

  2. String delimiters:

    • Double quotes ("): Escaped characters are interpreted.
      var str = "abc\nabc" // output contains newline
      
    • Backticks (`): String literal is output as-is, including newlines and special characters. Useful for preventing attacks or outputting source code.
      var str string = `abc\nabc` // output is literal
      
  3. String concatenation uses the + operator:

    var str string = "hello " + "world"
    str += "!"
    
  4. Multi-line strings: When a string is too long, break it across lines as follows:

    // Correct
    str := "hello" +
        " world!"
    fmt.Println(str)
    
    // Incorrect
    str := "hello "
        + "world!"
    fmt.Println(str)
    

Pointers

  1. Basic data types store values directly; they are called value types.
  2. To get the address of a variable, use &. For example, var num int; &num gives the adress of num.
  3. A pointer variable stores an address pointing to the actual value. Example: var ptr *int = &num.
  4. To access the value a pointer points to, use *. For example, if var ptr *int, then *ptr gives the pointed value.

Pointer details:

  • Every value type has a corresponding pointer type of the form *dataType. For instance, int corresponds to *int, float64 to *float64, etc.
  • Value types include: basic data types, arrays, and structs.

Value Types vs. Reference Types

Value types: Store values directly; memory is usually allocated on the stack.

Reference types: Store an address that points to the actual data (values); memory is typically allocated on the heap. When no variable references an address, the data becomes garbage and is reclaimed by GC.

Distinction:

  • Value types: basic data types (int series, float series, bool, string), arrays, and structs.
  • Reference types: pointers, slices, maps, channnels, interfaces.

Default Values of Basic Data Types

In Go, every data type has a default value (zero value) when no value is assigned.

Data Type Default Value
Integer types 0
Floating-point types 0
String "" (empty string)
Boolean false
package main

import "fmt"

func main() {
    var a int
    var b float32
    var isTrue bool
    var str string

    // %v prints the value in its default format
    fmt.Printf("a = %v, b = %v, isTrue = %v, str = %v", a, b, isTrue, str)
    fmt.Println()
}

Type Conversion Between Basic Types

Unlike Java or C, Go requires explicit conversion when assigning between different types. Data types in Go cannot be automatically converted.

Syntax: type(variable) converts the value variable to type type.

type is the target data type (e.g., int32, int64, float32). variable is the source variable.

var num int = 42
var float float64 = float64(num)
var ui uint8 = uint8(float)
fmt.Println(num, float, ui)

Important Notes

  1. Conversion can go from a smaller range to a larger range, or vice versa.
  2. The conversion is applied to the value stored in the variable; the variable's own type does not change.
  3. Converting from a larger type to a smaller one (e.g., int64 to int8) compiles without error, but the result may overflow, differing from expectations.
  4. All conversions must be explicit; automatic conversion is not allowed.
package main
import "fmt"

func main() {
    var n1 int32 = 12
    var n2 int64
    var n3 int8

    // n2 = n1 + 20 // Error: int32 to int64 (implicit)
    // n3 = n1 + 20 // Error: int32 to int8 (implicit)

    n2 = int64(n1) + 20 // Correct
    n3 = int8(n1) + 20  // Correct
}
  1. If an int8 variable starts at 0 and keeps incrementing by 1, its value cycles from 0 to 127, then -128 to -127, and back to 0...127, never exceeding the type's range.

Converting Other Basic Types to String

Often, we need to convert numeric types to strings, or vice versa.

Method 1: fmt.Sprintf

func Sprintf(format string, a ...interface{}) string

Sprintf returns a formatted string based on the format parameter.

package main

import "fmt"

func main() {
    var num1 int = 99
    var num2 float64 = 23.456
    var isTrue bool = true
    var char byte = 'A'

    var str string

    str = fmt.Sprintf("%d", num1)
    fmt.Printf("str type: %T, str = %q\n", str, str)

    str = fmt.Sprintf("%f", num2)
    fmt.Printf("str type: %T, str = %q\n", str, str)

    str = fmt.Sprintf("%t", isTrue)
    fmt.Printf("str type: %T, str = %q\n", str, str)

    str = fmt.Sprintf("%d", char)
    fmt.Printf("str type: %T, str = %q\n", str, str)
}

Output:

str type: string, str = "99"
str type: string, str = "23.456000"
str type: string, str = "true"
str type: string, str = "65"

Method 2: Functions from the strconv package

package main

import (
    "fmt"
    "strconv"
)

func main() {
    var num1 int = 99
    var num2 float64 = 23.456
    var isTrue bool = true

    var str string

    str = strconv.FormatInt(int64(num1), 10)
    str = strconv.Itoa(num1)
    fmt.Printf("str type: %T, str = %q\n", str, str)

    str = strconv.FormatFloat(num2, 'f', 10, 64)
    fmt.Printf("str type: %T, str = %q\n", str, str)

    str = strconv.FormatBool(isTrue)
    fmt.Printf("str type: %T, str = %q\n", str, str)
}

Output:

str type: string, str = "99"
str type: string, str = "23.4560000000"
str type: string, str = "true"

Converting String to Other Basic Types

Method: Use functions from the strconv package.

package main

import (
    "fmt"
    "strconv"
)

func main() {
    var str string = "true"
    var str1 string = "123456"
    var str2 string = "123.456"

    var isTrue bool
    var num int64
    var num2 float64

    isTrue, _ = strconv.ParseBool(str)
    fmt.Printf("type: %T, value: %v\n", isTrue, isTrue)

    num, _ = strconv.ParseInt(str1, 10, 64)
    fmt.Printf("type: %T, value: %v\n", num, num)

    num2, _ = strconv.ParseFloat(str2, 64)
    fmt.Printf("type: %T, value: %v\n", num2, num2)
}

Output:

type: bool, value: true
type: int64, value: 123456
type: float64, value: 123.456

Caution: When converting a string to another basic type, ensure the string represents valid data. For example, converting "123" to an integer works, but converting "hello" to an integer yields 0. Similarly for other types: invalid float strings produce 0.0, invalid bool strings produce false.

Tags: goData Types

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.