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.