Data Types in Go

By Syncfusion®, Inc. · Last updated

Go's number types, strings, booleans, bytes and runes, zero values, nil, type inference, and converting between types with T(x) and strconv.

What Are Data Types?

Data type = the kind of value a variable can hold.

The type tells Go two things:

  • what the value is, like a number or text
  • how much memory the box needs

For example:

  • 92 is a whole number: type int
  • 91.5 is a number with a decimal point: type float64
  • "Asha" is text: type string
  • true is a yes or no answer: type bool

Simple lesson: every value in Go has a type, and the type decides what you can do with it.

A Real-World Example

Think of the school's report card form.

  • The Name box only takes letters.
  • The Marks box only takes numbers.
  • The Passed? box only takes a tick or a cross.

If someone writes "ninety" in the Marks box, the office sends the form back.

Now the mapping:

  • Each box = a variable.
  • What the box accepts = its type.
  • Sending the form back = Go stopping your program before it runs.

Go is statically typed.

Static typing = Go checks every type before the program runs.

  • Mistakes are found on your computer, not by your users.
  • A variable keeps the same type for its whole life.

What You Will Learn

In this lesson, you will learn:

  1. The number types: integers, floats and complex numbers.
  2. The string, bool, rune and byte types.
  3. Zero values: what a variable holds before you give it a value.
  4. What nil means.
  5. How Go guesses a type for you (type inference).
  6. How to convert a value from one type to another.

Numeric Types

Go has three families of number types.

The three number families

Integer Types

Integer = a whole number, like -3, 0 or 250.

Each integer type has a size in bits. Bit = the smallest piece of computer memory: a 0 or a 1.

Click each type and compare its size and range.

Look at two things:

  • More bits = a bigger range of numbers.
  • uint types are never negative, so their range goes higher.
TypeSizeRange
int88 bits-128 to 127
int1616 bits-32,768 to 32,767
int3232 bitsabout -2.1 billion to 2.1 billion
int6464 bitsabout -9.2 × 10¹⁸ to 9.2 × 10¹⁸
uint88 bits0 to 255
uint1616 bits0 to 65,535
uint3232 bits0 to about 4.2 billion
uint6464 bits0 to about 1.8 × 10¹⁹

int, uint and uintptr

  • int = 64 bits on most computers today. Use it by default.
  • uint = the same size as int, but never negative.
  • uintptr = an integer big enough to hold a memory address. Only low-level code uses it.

Integer types

package main

import (
	"fmt"
	"math"
)

func main() {
	var students int = 42
	var floor int8 = -2
	var pages uint = 350
	fmt.Println(students, floor, pages)
	fmt.Println(math.MaxInt8, math.MinInt8, math.MaxUint8)
}
42 -2 350
127 -128 255
  • The math package has the limits of each type, like math.MaxInt8.

Overflow: When a Number Is Too Big

Overflow = a value goes past the largest number its type can hold.

Press Play to see it happen.

An int8 goes past 127

  • Go does not stop the program on overflow while it runs.
  • The number wraps around, like a car's trip meter going from 999 to 000.
  • So choose a type big enough for your numbers. int is usually safe.

Float Types

Float = a number with a decimal point, like 3.14 or -0.5.

  • float32 keeps about 7 correct digits.
  • float64 keeps about 15 correct digits.

float32 vs float64

package main

import "fmt"

func main() {
	var a float32 = 1.0 / 3
	var b float64 = 1.0 / 3
	fmt.Println(a)
	fmt.Println(b)
}
0.33333334
0.3333333333333333
  • float64 keeps many more digits, so its answer is more exact.
  • Go uses float64 when you write x := 2.5.

Complex Types

Complex number = a number with a real part and an imaginary part, written like 3 + 4i.

  • complex64 uses two float32s.
  • complex128 uses two float64s.
  • real(z) gives the real part. imag(z) gives the imaginary part.

A complex number

package main

import "fmt"

func main() {
	z := complex(3, 4)
	fmt.Println(z, real(z), imag(z))
}
(3+4i) 3 4

Simple lesson: use int for whole numbers and float64 for decimals, unless you have a special reason.

Text and True/False Types

The string Type

String = a piece of text, written in double quotes.

  • "Green Valley School" is a string.
  • "" is an empty string: text with nothing in it.
  • + joins two strings.
  • len() gives the length in bytes.

Strings

package main

import "fmt"

func main() {
	first := "Asha"
	last := "Rao"
	full := first + " " + last
	fmt.Println(full, len(full))
}
Asha Rao 8

You will learn much more in Strings.

The bool Type

bool = a value that is only true or false.

  • Use it for yes or no questions.
  • Comparisons like marks >= 35 give a bool.

Booleans

package main

import "fmt"

func main() {
	marks := 72
	passed := marks >= 35
	isMonitor := false
	fmt.Println(passed, isMonitor)
}
true false

The byte Type

byte = another name for uint8. It holds one byte of data, from 0 to 255.

  • Files and network data are made of bytes.
  • An English letter like 'g' fits in one byte.

The rune Type

rune = another name for int32. It holds one Unicode character.

Unicode = a list that gives every character in every language its own number.

  • 'A' is number 65.
  • 'अ' (Hindi) is number 2309.
  • Single quotes ' ' make a rune. Double quotes " " make a string.

byte and rune

package main

import "fmt"

func main() {
	var b byte = 'g'
	var r rune = 'अ'
	fmt.Println(b, string(b))
	fmt.Println(r, string(r))
}
103 g
2309 अ
  • Printing a byte or rune shows its number.
  • string(...) turns it back into a character.

Type some text below and compare bytes and runes.

  • English letters use 1 byte each.
  • Hindi letters and emoji use 3 or 4 bytes each.
  • So len() counts bytes, not characters.

Simple lesson: string is text, bool is true or false, byte is one byte, and rune is one character.

Zero Values

Zero value = the value Go puts in a variable when you do not give one.

Go never leaves a variable empty by accident.

TypeZero value
Numbers (int, float64, ...)0
boolfalse
string"" (empty text)
Pointernil
Slicenil
Mapnil
Interface (like error)nil

Zero values

package main

import "fmt"

func main() {
	var marks int
	var price float64
	var passed bool
	var name string
	var p *int
	var list []int
	var ages map[string]int
	var err error
	fmt.Println(marks, price, passed)
	fmt.Printf("%q\n", name)
	fmt.Println(p, list, ages, err)
}
0 0 false
""
<nil> [] map[] <nil>
  • %q prints the string inside quotes, so you can see it is empty.
  • An empty slice prints as [], an empty map as map[].
  • Pointers, slices and maps come in Pointers, Slices and Maps.

Simple lesson: a new variable always starts with its zero value: 0, false, "" or nil.

nil

nil = "nothing here yet". It is the zero value for pointers, slices, maps, channels, functions and interfaces.

Think of an empty parking slot with a number painted on it.

  • The slot exists.
  • No car is parked there yet.

nil is that empty slot.

Where nil Appears

  • nil pointer: a pointer that points to nothing. See Pointers.
  • nil slice: a list with no storage yet. It still works with len() and append.
  • nil map: you can read from it, but writing to it crashes the program.
  • nil interface: for example, an error that is nil means "no error".

nil values

package main

import "fmt"

func main() {
	var list []int
	var ages map[string]int
	var err error
	fmt.Println(list == nil, len(list))
	fmt.Println(ages == nil, ages["Asha"])
	fmt.Println(err == nil)
}
true 0
true 0
true
  • A nil slice has length 0.
  • Reading a missing key from a nil map gives the zero value.
  • err == nil is how Go programs check "did anything go wrong?". You will use it in Error Handling.

Writing to a nil map crashes the program: panic: assignment to entry in nil map.

You will learn to create maps safely in Maps.

Simple lesson: nil means "no value yet", and it belongs to pointers, slices, maps and interfaces.

Type Inference

Type inference = Go works out the type from the value, so you do not have to write it.

Type Inference with :=

You writeGo picks
count := 10int
price := 9.5float64
name := "Ravi"string
ok := truebool
letter := 'A'rune
z := 2 + 3icomplex128

See the type Go picked

package main

import "fmt"

func main() {
	count := 10
	price := 9.5
	letter := 'A'
	fmt.Printf("%T %T %T\n", count, price, letter)
}
int float64 int32
  • %T prints the type of a value.
  • rune prints as int32, because they are the same type.

Explicit Types vs Inference

Explicit type = you write the type yourself.

  • Inference: price := 9.5. Short, and Go picks float64.
  • Explicit: var price float32 = 9.5. Use it when you want a type Go would not pick.
  • Most Go code uses inference inside functions.

Simple lesson: Go guesses the type from the value, and you write it yourself only when you need a different one.

Type Conversion

Type conversion = making a value of one type from a value of another type.

Go never converts types by itself. You must ask, by writing the type like a function: float64(x).

Explicit Conversion

Run this. It adds an int and a float64.

Mixing types is not allowed

package main

import "fmt"

func main() {
	marks := 45
	bonus := 2.5
	fmt.Println(marks + bonus)
}
  • Go stops with an error like invalid operation: marks + bonus (mismatched types int and float64).
  • Go will not mix an int and a float64.
  • Fix: convert one of them, like float64(marks) + bonus.

Numeric Conversion

Press Play and watch each conversion.

Converting between number types

  • float64(x) turns a number into a float.
  • int(x) cuts off everything after the decimal point: int(price) is 9 when price is 9.99.
  • int(9.99) with the number typed in directly does not build, because Go sees the decimals would be lost.
  • Dividing two ints also drops the decimal part: 7 / 2 is 3.

Integer division vs float division

package main

import "fmt"

func main() {
	fmt.Println(7 / 2)
	fmt.Println(float64(7) / 2)
	price := 9.99
	fmt.Println(int(price))
}
3
3.5
9

String Conversion

Numbers and text need the strconv package (string conversion).

FunctionDoesExample
strconv.Itoa(n)int to stringstrconv.Itoa(99) gives "99"
strconv.Atoi(s)string to intstrconv.Atoi("42") gives 42
strconv.ParseFloat(s, 64)string to float64"3.75" gives 3.75
strconv.ParseBool(s)string to bool"true" gives true
fmt.Sprint(x)anything to stringfmt.Sprint(12) gives "12"

Text to number and back

package main

import (
	"fmt"
	"strconv"
)

func main() {
	n, err := strconv.Atoi("42")
	fmt.Println(n+1, err)

	_, err = strconv.Atoi("forty")
	fmt.Println(err)

	label := "Roll no: " + strconv.Itoa(17)
	fmt.Println(label)
}
43 <nil>
strconv.Atoi: parsing "forty": invalid syntax
Roll no: 17
  • Atoi gives back two values: the number, and an error.
  • If the text is not a number, the error says so.
  • Always check the error when the text comes from a user.

string(65) does not give "65". It gives "A", the character with number 65.

To turn a number into its digits, use strconv.Itoa(65).

Easy way to remember

  • Number to number: float64(x), int(x)
  • Number to text: strconv.Itoa(n)
  • Text to number: strconv.Atoi(s), and check the error

Simple lesson: Go never mixes types by itself, so you convert with T(x) for numbers and strconv for text.

TL;DR

  1. Data type = the kind of value a variable holds.
  2. Integers = int, int8 ... int64, uint, uint8 ... uint64, uintptr.

    • Use int by default.
    • Overflow = going past the limit wraps around.
  3. Floats = float32, float64. Use float64.
  4. Complex = complex64, complex128.
  5. string = text. bool = true or false.

    • byte = uint8. rune = int32, one Unicode character.
  6. Zero value = 0, false, "" or nil.

    • nil = "nothing yet" for pointers, slices, maps and interfaces.
  7. Type inference = x := 2.5 makes a float64.
  8. Conversion = float64(x), int(x), strconv.Itoa, strconv.Atoi.

Common mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
marks + 2.5 with an intGo mixes number typesConvert first: float64(marks) + 2.5mismatched types int and float64
int(price) to roundint() roundsint() cuts off the decimalsYou get 9, not 10.
7 / 2 for 3.5Division always keeps decimalsTwo ints give an intYou get 3.
string(65) for "65"It makes the digitsIt makes the character "A"Wrong text. Use strconv.Itoa.
Ignoring the Atoi errorThe text is always a numberCheck errA silent 0 instead of a number.
int8 for big numbersAny int type will doPick a type big enoughOverflow wraps to a wrong number.
'Hello' for textSingle quotes make stringsSingle quotes make one runeA build error.

Check Yourself

Exercises

What to Remember

  • Every value has a type. Go checks types before the program runs.
  • Use int for whole numbers, float64 for decimals, string for text, bool for yes or no.
  • byte is one byte. rune is one character.
  • New variables start at their zero value: 0, false, "" or nil.
  • Go never converts types for you. Use float64(x), int(x), strconv.Itoa and strconv.Atoi.

Next: Operators. You will learn how to do maths, compare values and combine true or false answers.