Data Types & Constants (iota)
You know the four headline types already. Now you'll meet Go's full numeric family (sized ints, unsigned ints, floats), understand the real difference between byte , rune and string , and master iota — Go's elegant way to build enums and bit flags without typing a single number by hand.
Learn Data Types & Constants (iota) in our free Go course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.
Part of the free Go course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
1️⃣ The Numeric Family
Plain int is 64 bits on modern machines and is what you'll use 95% of the time. But Go gives you precise control when you need it: int8/16/32/64 for signed whole numbers of a specific size, uint variants for unsigned (zero-and-up) values, and float32/float64 for decimals. Reach for the sized types when memory matters (huge slices) or when an external format demands an exact width.
Your turn — fill in the three blanks. Remember a colour channel is 0–255 (perfect for an unsigned 8-bit type), and you must convert before mixing sizes.
2️⃣ Bytes, Runes & Strings
This trips up almost everyone coming from other languages. A Go string is a sequence of bytes , and len(s) counts those bytes — not characters. Because Go uses UTF-8, an accented or non-Latin character can take 2–4 bytes. A rune (an alias for int32 ) represents one real Unicode character, and ranging over a string decodes runes for you. A byte is an alias for uint8 .
3️⃣ Constants & iota
Go has no enum keyword. Instead it gives you iota — a counter that resets to 0 at the start of each const (...) block and increments by one on every line. Write the expression once and Go repeats it down the list. Pair it with a named type (like type Weekday int ) and you get type-safe enums. With 1 << iota you get powers of two — perfect for bit flags you can combine with | .
Your turn — complete this log-level enum. The first line starts the counter; the rest follow automatically.
These lines define a bit-flag constant block, but they're scrambled. Put them in the correct order so the program compiles and prints Write = 2 (assume a func main wraps the print).
Why: the package and import come first. The const ( block must open before its members. Read = 1 << iota sets the pattern on line 0 (value 1), and Write on the next line repeats it at iota=1, giving 1 << 1 = 2 . The block must be closed with ) before any code references Write .
Predict the output before you reveal the answer.
5 — the é is two bytes in UTF-8, so the 4-character word is 5 bytes long. Count characters with utf8.RuneCountInString to get 4.
2 — iota is 0 for A, 1 for B, 2 for C. The = iota expression repeats implicitly on each line.
B — Unicode code point 66 is the capital letter B, and %c prints the character for that value.
Rarely for everyday counters. Use a sized type when you're matching a binary file format, a network protocol, or trimming memory in a very large slice. Otherwise plain int is idiomatic and fast.
Q: Why does len on a string give a strange number?
len counts bytes, and UTF-8 uses multiple bytes for non-ASCII characters. To count characters, range over the string (which yields runes) or call utf8.RuneCountInString .
Yes — assign that line to the blank identifier _ . A common pattern is _ = iota on the first line so your real values start at 1.
Bring it together: an iota enum plus a float64 for mass. Write it yourself and match the example output in the comments.
Practice quiz
What is the range of an int8?
- 0 to 255
- 0 to 127
- -128 to 127
- -256 to 255
Answer: -128 to 127. A signed 8-bit integer (int8) holds values from -128 to 127.
What does len("café") return in Go?
- 5
- 4
- 3
- 8
Answer: 5. len counts bytes, and é is two bytes in UTF-8, so the 4-character word is 5 bytes long.
A rune in Go is an alias for which type?
- uint8
- int64
- byte
- int32
Answer: int32. A rune is an alias for int32 and represents a single Unicode code point.
A byte in Go is an alias for which type?
- int8
- uint8
- int32
- rune
Answer: uint8. byte is an alias for uint8 — one raw, unsigned 8-bit value.
What does fmt.Printf("%c", rune(66)) print?
- B
- 66
- A
- b
Answer: B. Unicode code point 66 is the capital letter B, and %c prints the character for that value.
Which floating-point type is Go's default and more precise?
- float32
- float16
- float64
- decimal
Answer: float64. float64 is the default float type in Go and offers roughly 15 digits of precision.
What is the value of letter in: var letter rune = 'A'; fmt.Println(letter)?
- A
- 65
- 0
- 'A'
Answer: 65. A rune is an integer type, and the Unicode value of 'A' is 65, which is what Println shows.
Given const ( A = iota; B; C ), what does C equal?
- 0
- 1
- 3
- 2
Answer: 2. iota is 0 for A, 1 for B, and 2 for C — the = iota expression repeats implicitly each line.
Will two different integer types like int and int64 mix automatically in an expression?
- Yes
- No — you must convert explicitly
- Only if same size
- Only with floats
Answer: No — you must convert explicitly. Go never mixes numeric types implicitly; you must convert, e.g. int64(x) + y.
How should you count the actual characters in a UTF-8 string?
- len(s)
- cap(s)
- range over the string or utf8.RuneCountInString(s)
- s.length
Answer: range over the string or utf8.RuneCountInString(s). len counts bytes; range over the string yields runes, or use utf8.RuneCountInString to count characters.