If you are looking for golang string to uint8, golang uint8 to string, uint8 golang, or go uint8, this guide covers both directions: parsing numeric text into a byte-sized value, turning a uint8 into text (digits versus a character), and moving between string and []uint8 / []byte. When I drafted it I re-ran the snippets with go run on Go 1.22 (Linux) so the errors and outputs here match what you should see locally. For general strconv patterns, see strconv in Go; for fmt verbs when you build messages, see string formatting in Go; for casts, see type casting in Go.
Tested on: Go 1.22 on 64-bit Linux; each program listing was run with
go runwhile this article was revised.
Quick reference: uint8 conversions
| Goal | Use | Example |
|---|---|---|
Convert numeric string to uint8 |
strconv.ParseUint(s, 10, 8) |
"255" → uint8(255) |
Convert decimal uint8 to string |
strconv.FormatUint(uint64(v), 10) |
uint8(65) → "65" |
Convert uint8 to string with Itoa |
strconv.Itoa(int(v)) |
uint8(65) → "65" |
Convert uint8 to character |
string(v) or string(rune(v)) |
uint8(65) → "A" |
Convert string to []uint8 |
[]uint8(s) or []byte(s) |
"Go" → [71 111] |
Convert []uint8 to string |
string(bytes) |
[]uint8{71, 111} → "Go" |
Convert hex string to uint8 |
strconv.ParseUint(s, 16, 8) |
"ff" → 255 |
Convert binary string to uint8 |
strconv.ParseUint(s, 2, 8) |
"11111111" → 255 |
Direct string(v) on a uint8 treats the value as a Unicode code point; see Numeric string vs character conversion for contrast with digit strings.
uint8, byte, and string Basics
uint8 range in Go
uint8 is an unsigned 8-bit integer: values 0 through 255.
byte is an alias for uint8
The language spec defines byte as an alias for uint8. The name byte usually signals raw data or part of a string; the name uint8 usually signals a small numeric counter or component.
String indexing returns byte values
In Go, s[i] has type byte (uint8) and returns the i-th byte, not necessarily a full Unicode character:
package main
import "fmt"
func main() {
s := "Hello"
fmt.Println(s[1]) // 101 ('e')
}Multi-byte UTF-8 characters span several indices:
package main
import "fmt"
func main() {
s := "é"
fmt.Println(len(s)) // 2 bytes in UTF-8
fmt.Println(s[0]) // first byte only, not the whole character
}When I ran that, len(s) printed 2 and s[0] printed 195. Use range over the string when you need whole runes.
Convert String to uint8 in Go
Use strconv.ParseUint for string to uint8
strconv.ParseUint is the unsigned counterpart to ParseInt; the docs note that a sign prefix is not permitted. The third argument is bitSize: use 8 so values outside 0–255 return an error instead of surprising you after a cast.
package main
import (
"fmt"
"strconv"
)
func main() {
s := "255"
n, err := strconv.ParseUint(s, 10, 8)
if err != nil {
fmt.Println("error:", err)
return
}
value := uint8(n)
fmt.Printf("value: %v, type: %T\n", value, value)
}Why ParseUint instead of Atoi or ParseInt?
| Function | Issue for uint8 |
|---|---|
strconv.Atoi |
Parses int; you must validate range before uint8(n) or values wrap |
strconv.ParseInt |
Signed; not the most direct model for unsigned bytes |
strconv.ParseUint |
Unsigned; bitSize 8 enforces the uint8 range at parse time |
Handle invalid syntax and out-of-range values
package main
import (
"fmt"
"strconv"
)
func main() {
for _, s := range []string{"42", "256", "12x"} {
_, err := strconv.ParseUint(s, 10, 8)
fmt.Printf("%q -> %v\n", s, err)
}
}When I ran that loop, "42" produced a nil error (it fits in uint8), "256" failed with value out of range, and "12x" failed with invalid syntax. I kept a valid string in the list so success sits next to the two failure shapes I see most often.
Always check err before using the result; 0 is a valid parse, so a missing error check can hide failures.
Convert decimal, binary, and hexadecimal strings to uint8
package main
import (
"fmt"
"strconv"
)
func main() {
dec, _ := strconv.ParseUint("200", 10, 8)
hexv, _ := strconv.ParseUint("ff", 16, 8)
bin, _ := strconv.ParseUint("11111111", 2, 8)
fmt.Println(uint8(dec), uint8(hexv), uint8(bin))
}Convert uint8 to String in Go
Convert uint8 to numeric string using strconv.FormatUint
package main
import (
"fmt"
"strconv"
)
func main() {
v := uint8(65)
fmt.Println(strconv.FormatUint(uint64(v), 10))
}Convert uint8 to numeric string using strconv.Itoa
package main
import (
"fmt"
"strconv"
)
func main() {
v := uint8(65)
fmt.Println(strconv.Itoa(int(v)))
}Convert uint8 to character string using string()
For a single ASCII code point, string(rune(v)) reads clearly. string(v) where v is an untyped constant or you convert through rune avoids surprises; converting an integer type directly to string is easy to misuse for wider types—stick to rune for code points.
Numeric String vs Character Conversion
These three outputs differ; that distinction drives most confusion for uint8 to string golang searches.
| Input | Code | Output | Meaning |
|---|---|---|---|
uint8(65) |
strconv.FormatUint(uint64(v), 10) |
"65" |
Decimal digits as text |
uint8(65) |
strconv.Itoa(int(v)) |
"65" |
Same numeric text for ASCII-safe values |
uint8(65) |
string(rune(v)) |
"A" |
The Unicode character U+0041 |
strconv.FormatUint formats the number in the chosen base. string(rune(v)) builds a one-rune string from the code point.
Why string(uint8(65)) returns "A"
With a typed uint8 value, string(v) still follows the conversion rules: the value is interpreted as a code point when converted to string from integer types. Prefer string(rune(v)) in new code to signal intent, and use FormatUint when you want "65".
Why strconv.FormatUint(uint64(v), 10) returns "65"
It is the decimal rendering of the unsigned value, not a rune interpretation.
Convert String to Other Unsigned Types
The same ParseUint call works with a larger bitSize argument:
| Target | Call |
|---|---|
uint |
strconv.ParseUint(s, 10, 0) (size follows uint on the platform) or an explicit width |
uint16 |
strconv.ParseUint(s, 10, 16) then uint16(n) |
uint32 |
strconv.ParseUint(s, 10, 32) then uint32(n) |
uint64 |
strconv.ParseUint(s, 10, 64) (or bit size 0 per docs for uint64) |
Check error every time, then cast to the narrower type you store.
Convert Between string and []uint8
byte is an alias for uint8, so []byte and []uint8 share the same element type and you can convert between those slice types when needed.
Convert string to []uint8 or []byte
package main
import "fmt"
func main() {
s := "Go"
bytes := []uint8(s)
text := string(bytes)
fmt.Println(bytes)
fmt.Println(text)
}Output:
[71 111]
GoA Go string holds arbitrary bytes; UTF-8 in literals maps code points to bytes. See the language tour on strings for the mental model.
Convert []uint8 or []byte to string
string(slice) copies the bytes into an immutable string. Avoid repeated conversions in hot loops if profiling shows cost; share one conversion result when possible.
Common Use Cases
Parse user input into uint8
Read text from a flag or form field, trim with strings.TrimSpace, then ParseUint(..., 10, 8).
Read byte values from strings
Use indexing s[i] or convert to []byte(s) when you need to mutate or inspect every byte.
Convert ASCII byte values to characters
After validating a value is in ASCII range, string(rune(b)) gives the character.
Parse RGB color values
package main
import (
"fmt"
"strconv"
)
func main() {
r, errR := strconv.ParseUint("240", 10, 8)
g, errG := strconv.ParseUint("128", 10, 8)
b, errB := strconv.ParseUint("64", 10, 8)
if errR != nil || errG != nil || errB != nil {
return
}
fmt.Println(uint8(r), uint8(g), uint8(b))
}Parse binary or hex byte values
Use base 2 or 16 with bitSize 8, as in the cheat sheet.
Common Mistakes
Using string(v) when you want "65"
package main
import (
"fmt"
"strconv"
)
func main() {
var v uint8 = 65
fmt.Println(string(v)) // A (code point)
fmt.Println(strconv.FormatUint(uint64(v), 10)) // 65 (digits)
}Using strconv.Atoi without checking uint8 range
package main
import (
"fmt"
"strconv"
)
func main() {
n, err := strconv.Atoi("300")
if err != nil {
return
}
value := uint8(n) // wraps: 300 % 256 == 44
fmt.Println(value)
}When I ran that, it printed 44. Use ParseUint(s, 10, 8) so an oversized literal fails instead.
Using ParseInt instead of ParseUint for unsigned values
You can use ParseInt with a positive check, but ParseUint matches unsigned intent and rejects -1 cleanly.
Trying to parse negative numbers into uint8
package main
import (
"fmt"
"strconv"
)
func main() {
_, err := strconv.ParseUint("-1", 10, 8)
fmt.Println(err)
}That prints an invalid syntax style error from strconv (unsigned input cannot have a minus sign).
Confusing uint8 value with ASCII character
Remember the numeric versus character table in Numeric string vs character conversion.
Ignoring conversion errors
Treat parse errors as first-class; do not cast before you know err == nil.
Confusing byte position with character position
See the é example under String indexing returns byte values.
Go uint8 Conversion Cheat Sheet
Which conversion should you use?
- Numeric text →
uint8: usestrconv.ParseUintwithbitSize8, then cast after checkingerr. uint8→ digit string: usestrconv.FormatUint(uint64(v), 10)orstrconv.Itoa(int(v))for ASCII-safe ranges.uint8→ character: usestring(v)orstring(rune(v))when the value is the code point you intend (runemakes intent obvious in reviews).- Raw bytes ↔ text: use
[]byte(s)andstring(slice); that is separate from parsing"255"as a number.

