Skip to main content

What built-in data types are available in Go?

Built-in Data Types in Go

In Go, types can be divided into several main categories: boolean, numeric, string, composite, and special types.

1. Boolean Type

bool

Stores one of two values: true or false.

var isActive bool = true
var isReady bool = false

The zero value of bool is false.

2. Numeric Types

Signed Integers

Signed integers can store positive numbers, negative numbers, and zero.

TypeSizeRange
int81 bytefrom -128 to 127
int162 bytesfrom -32,768 to 32,767
int324 bytesapproximately -2.1 billion to 2.1 billion
int648 bytesapproximately -9.2 × 10¹⁸ to 9.2 × 10¹⁸
int4 or 8 bytesdepends on the platform and implementation
var age int = 30
var bigNumber int64 = 9_000_000_000

int is usually 32 bits on 32-bit systems and 64 bits on 64-bit systems.

However, int and int64 are still different types, even when they occupy the same amount of memory:

var a int = 10
var b int64 = int64(a)

You cannot assign an int value to an int64 variable without an explicit type conversion.

Unsigned Integers

Unsigned integers store only positive numbers and zero.

TypeSizeRange
uint81 bytefrom 0 to 255
uint162 bytesfrom 0 to 65,535
uint324 bytesfrom 0 to approximately 4.2 billion
uint648 bytesfrom 0 to approximately 1.8 × 10¹⁹
uint4 or 8 bytesdepends on the platform
uintptrpointer sizeused for low-level work with memory addresses
var count uint = 100
var port uint16 = 8080

uintptr should not be used as a regular pointer. It is mainly needed when working with low-level code and the unsafe package.

Floating-Point Numbers

Floating-point types are used to store fractional numbers.

TypeSizeApproximate precision
float324 bytesapproximately 7 significant digits
float648 bytesapproximately 15–16 significant digits
var price float64 = 19.99
var pi float32 = 3.14159

These numbers are stored approximately in the following form:

sign × significand × 2^exponent

Because of the binary format, many decimal fractions cannot be represented exactly.

a := 0.1
b := 0.2

fmt.Println(a + b)      // 0.30000000000000004
fmt.Println(a+b == 0.3) // false

For monetary values, it is better to use:

priceInCents := 1999

Complex Numbers

A complex number consists of a real part and an imaginary part.

TypeNumber components
complex64two float32 components
complex128two float64 components
var c1 complex64 = 1 + 2i
var c2 complex128 = 3 + 4i

Complex numbers are mainly used in mathematical and scientific calculations.

3. Strings and Types for Working with Text

string

A string is an immutable sequence of bytes.

var name string = "Hello"

A string can contain any bytes. UTF-8 encoding is usually used for text, but Go does not require every string to contain valid UTF-8.

The len function returns the number of bytes, not the number of characters:

name := "Привет"

fmt.Println(len(name)) // 12

Each Russian letter in this example occupies two bytes in UTF-8.

Strings are immutable, which means that you cannot replace an individual byte inside a string.

s := "hello"

// s[0] = 'H' // compilation error

s = "Hello"

Accessing a string by index returns a byte:

s := "Hello"

fmt.Println(s[0])         // 72
fmt.Println(string(s[0])) // H

byte

byte is an alias for uint8.

It is used for working with individual bytes, files, network data, and ASCII characters.

var b byte = 'A'

fmt.Println(b)         // 65
fmt.Println(string(b)) // A

rune

rune is an alias for int32.

It usually represents one Unicode code point.

var r rune = 'Я'

fmt.Println(r)         // 1071
fmt.Println(string(r)) // Я

A rune does not always represent one visible character. Some displayed characters may consist of several Unicode code points.

The range keyword is used to iterate over a string by runes:

for index, r := range "Привет" {
	fmt.Println(index, r, string(r))
}

4. Composite Types

Array

An array stores a fixed number of elements of the same type.

var nums [3]int = [3]int{10, 20, 30}

nums[0] = 5

The length of an array is part of its type:

var a [3]int
var b [4]int

[3]int and [4]int are different types.

Arrays are copied when assigned:

a := [3]int{1, 2, 3}
b := a

b[0] = 100

fmt.Println(a) // [1 2 3]
fmt.Println(b) // [100 2 3]

Slice

A slice describes a section of an underlying array.

It stores:

nums := []int{1, 2, 3}

nums = append(nums, 4)

A slice does not have a fixed size:

fmt.Println(len(nums)) // length
fmt.Println(cap(nums)) // capacity

append may use the existing underlying array or create a new one if the current capacity is insufficient.

nums := make([]int, 0, 3)

nums = append(nums, 10)
nums = append(nums, 20)

Map

A map stores key-value pairs.

ages := map[string]int{
	"Alice": 30,
	"Bob":   25,
}

fmt.Println(ages["Alice"]) // 30

You can check whether a key exists when retrieving a value:

age, exists := ages["Alice"]

if exists {
	fmt.Println(age)
}

Only comparable types can be used as map keys.

Valid map key types:

map[string]int{}
map[int]string{}
map[[2]int]string{}

Invalid map key types:

// map[[]int]string{}        // compilation error
// map[map[string]int]int{}  // compilation error
// map[func()]string{}       // compilation error

Slices, maps, and functions cannot be used as map keys.

Struct

A struct combines several named fields into one type.

type User struct {
	Name string
	Age  int
}

u := User{
	Name: "Ivan",
	Age:  25,
}

Methods can be declared for a named struct type:

func (u User) Greeting() string {
	return "Hello, " + u.Name
}

Usage:

fmt.Println(u.Greeting())

5. Pointers and Function Types

Pointer

A pointer stores the memory address of another value.

x := 10
p := &x

The & operator returns the address of a value:

p := &x

The * operator retrieves the value stored at that address:

fmt.Println(*p) // 10

A pointer can be used to change the original value:

*p = 20

fmt.Println(x) // 20

The zero value of a pointer is nil.

var p *int

fmt.Println(p == nil) // true

Function

Functions are values in Go.

They can be:

add := func(a, b int) int {
	return a + b
}

fmt.Println(add(2, 3)) // 5

You can declare a custom function type:

type Operation func(int, int) int
var op Operation = add

6. Channels

chan

A channel is used to transfer data between goroutines.

A goroutine is a lightweight function that can run concurrently with other functions.

ch := make(chan int)

go func() {
	ch <- 42
}()

value := <-ch

fmt.Println(value) // 42

The channel type determines what kind of data can be transferred through it:

chan int
chan string
chan User

Channels can be:

chan int   // bidirectional channel
chan<- int // send-only channel
<-chan int // receive-only channel

7. Interfaces

interface

An interface describes a set of methods.

type Stringer interface {
	String() string
}

A type automatically satisfies an interface if it implements all the required methods.

type User struct {
	Name string
}

func (u User) String() string {
	return u.Name
}

The User type now satisfies the Stringer interface.

var s Stringer = User{Name: "Alice"}

You do not need to explicitly declare that a type implements an interface.

any

any is an alias for the empty interface:

interface{}

It can store a value of any type.

var value any

value = 42
value = "hello"
value = true

A type assertion is used to retrieve a value of a specific type:

text, ok := value.(string)

if ok {
	fmt.Println(text)
}

8. Built-in error Interface

The error interface is used to represent errors.

It is declared approximately like this:

type error interface {
	Error() string
}

Example:

func divide(a, b float64) (float64, error) {
	if b == 0 {
		return 0, errors.New("division by zero")
	}

	return a / b, nil
}

Usage:

result, err := divide(10, 0)

if err != nil {
	fmt.Println(err)
	return
}

fmt.Println(result)

9. Aliases and Special Values

NameMeaning
bytealias for uint8
runealias for int32
anyalias for interface{}
errorbuilt-in interface for errors
nilabsence of a value for certain types
trueboolean constant
falseboolean constant

nil can be the value of:

var pointer *int
var slice []int
var users map[string]int
var ch chan int
var handler func()
var value any

All these variables initially have the value nil.

10. Zero Values

When a variable is declared without an initial value, Go automatically assigns the zero value of its type.

var i int
var f float64
var b bool
var s string
var p *int

Their values are:

i == 0
f == 0.0
b == false
s == ""
p == nil

For composite types:

var arr [3]int
var slice []int
var users map[string]int
var user User

Their zero values are:

arr   == [0 0 0]
slice == nil
users == nil

All fields of a struct also receive the zero values of their respective types.

A zero-value map is nil. You can read from it, but you cannot write to it.

var users map[string]int

fmt.Println(users["Alice"]) // 0

// users["Alice"] = 30 // panic

The map must be initialized before writing:

users = make(map[string]int)
users["Alice"] = 30

A zero-value slice is also nil, but it can be used with append:

var nums []int

nums = append(nums, 10)

Quick Reference

// Boolean type
bool

// String
string

// Signed integers
int
int8
int16
int32
int64

// Unsigned integers
uint
uint8
uint16
uint32
uint64
uintptr

// Floating-point numbers
float32
float64

// Complex numbers
complex64
complex128

// Aliases
byte // uint8
rune // int32
any  // interface{}

// Composite types
[N]T        // array
[]T         // slice
map[K]V     // map
struct      // struct

// Other types
*T          // pointer
func        // function
chan T      // channel
interface   // interface

Conclusion

The main built-in Go types are:

Go also provides the aliases byte, rune, and any, as well as the built-in error interface.

Serzh AI Academy — What built-in data types are available in Go?