| Tested on | RHEL 10.2 with Go 1.27.0 |
|---|---|
| Package | go 1.27.0 |
| Applies to | Any host with Go 1.20+ installed |
| Privilege | Normal user |
| Scope | Single byte widening, decimal text with strconv, fixed-width and varint binary with encoding/binary, large magnitudes with math/big, and reverse int-to-bytes patterns. Does not cover Protocol Buffers or full protocol design. |
| Related guides | Go bytes to string strconv in Go Convert int to string in Go Type casting in Go Golang tutorial |
A single byte is just uint8 and converts with int(b). A []byte has no single integer meaning: it might hold decimal text, fixed-width binary, a varint, or a large unsigned magnitude. There is no universal []byte → int conversion—first identify the encoding, then pick the API.
| Input | Use |
|---|---|
Single byte / uint8 |
int(b) |
[]byte("123") |
strconv.Atoi(string(b)) |
| Fixed 2/4/8-byte integer | encoding/binary |
| Varint-encoded integer | binary.Varint / binary.Uvarint |
| Arbitrarily large unsigned big-endian magnitude | big.Int.SetBytes |
Convert a single byte or uint8 to int
byte is a type alias for uint8. Widening to int preserves the numeric value from 0 through 255:
var b byte = 200
n := int(b) // 200No packages are required. This is not how you convert a []byte slice—one byte is a scalar; a slice needs an encoding interpretation.
Convert decimal text []byte to int
When the bytes represent decimal digits (and optional leading sign), convert to string and parse:
package main
import (
"fmt"
"strconv"
)
func main() {
b := []byte("123")
n, err := strconv.Atoi(string(b))
if err != nil {
fmt.Println(err)
return
}
fmt.Println(n)
}123After string(b), the text must match the integer syntax accepted by strconv.Atoi or strconv.ParseInt—decimal digits with an optional sign. []byte{54, 60, 70} fails because "6<F" is not valid decimal syntax, not because of a special UTF-8 rule for byte slices.
Always check err. Atoi returns (0, err) on failure; ignoring the error makes zero indistinguishable from a real zero.
Atoi vs ParseInt
Use strconv.Atoi for ordinary machine-sized decimal integers. Reach for strconv.ParseInt(s, base, bitSize) when you need an explicit base, a fixed maximum bit width, or an int64 result:
v, err := strconv.ParseInt(string(b), 10, 32) // int32 rangeFor unsigned decimal text, use strconv.ParseUint with the appropriate bit size.
Convert fixed-width binary bytes to an integer
If the bytes come from a protocol or file format, you must know the field width, byte order, and signedness before decoding.
When you already hold exactly four bytes in wire order, Uint32 is clearer than wrapping the slice in bytes.NewReader and binary.Read:
buf := []byte{0x00, 0x00, 0x00, 0x7b}
if len(buf) < 4 {
// handle short buffer
}
u := binary.BigEndian.Uint32(buf)123Use binary.LittleEndian.Uint32 when the format stores least-significant byte first. The same numeric value can appear as 00 00 00 7b in big-endian form or 7b 00 00 00 in little-endian form—the slice alone does not tell Go which convention applies.
BigEndian vs LittleEndian
Pick the endianness from your specification, not from the bytes on disk. Mixing encode and decode endianness silently produces the wrong integer.
Signed int32 and int64
For signed two's-complement wire data, read the unsigned width first, then reinterpret the bits:
signed := int32(binary.BigEndian.Uint32(buf))For eight-byte fields, use Uint64 / PutUint64 with the same pattern. On the wire, prefer fixed int16, uint16, int32, uint32, int64, and uint64 types rather than architecture-dependent int; convert to int in application code only when appropriate.
binary.Read remains useful when bytes arrive from an io.Reader or you want the decoder to advance a cursor—Uint32 on a slice you already have is the simpler path.
Decode varint-encoded bytes
Varints store smaller values in fewer bytes using a different encoding than ASCII decimal or fixed-width integers. Decode them with:
n, bytesRead := binary.Uvarint(buf) // unsigned
// or
n, bytesRead := binary.Varint(buf) // signedSample output for []byte{0xac, 0x02}:
300 2Interpret bytesRead carefully: greater than zero means success; zero means the buffer is too small; less than zero signals overflow (the magnitude of the negative value is the minimum buffer size needed). This is not interchangeable with Atoi or Uint32.
Convert large byte sequences with math/big
When the slice is an unsigned big-endian magnitude of arbitrary length, use math/big:
i := new(big.Int).SetBytes([]byte{0x01, 0x00, 0x01})
fmt.Println(i.String()) // 65537SetBytes interprets the bytes as an unsigned big-endian magnitude. It does not decode little-endian layouts or signed two's-complement formats automatically. The result is *big.Int, not a native Go int—convert or compare through big.Int methods when values may exceed machine word size.
Convert integers back to []byte
Match the reverse path to how you decoded.
Decimal text
[]byte(strconv.Itoa(n))Use strconv.FormatInt or FormatUint when you need int64 or a specific base.
Fixed-width binary
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(n))Use the same endianness and width on encode and decode.
Modern append APIs
Go 1.19 added AppendUint16, AppendUint32, and AppendUint64 through AppendByteOrder, plus AppendVarint and AppendUvarint. Generic binary.Append arrived in Go 1.23—do not confuse it with the 1.19 append helpers.
Common conversion mistakes
| Mistake | Fix |
|---|---|
Treating byte and []byte as equivalent |
A byte is one uint8; a slice needs an encoding interpretation |
Calling Atoi on arbitrary binary data |
Use it only for textual integers |
Ignoring the Atoi error |
Invalid input otherwise looks like a real zero |
| Guessing endian order | Follow the protocol or file format |
Calling Uint32 with fewer than 4 bytes |
Validate len(buf) before fixed-width reads |
Encoding native int directly on a wire protocol |
Use fixed-width integer types on the wire |
Assuming big.Int.SetBytes decodes signed data |
It reads an unsigned big-endian magnitude |
Saying generic binary.Append exists since Go 1.19 |
It was added in Go 1.23 |
Summary
There is no universal []byte to int conversion because a byte slice does not describe how the number was encoded. Widen a single byte with int(b). For slices, choose strconv when the bytes are decimal text, encoding/binary for fixed-width or varint wire layouts, and math/big for large unsigned magnitudes.
Check parse errors, validate buffer lengths, and match endianness to your format. Convert wire integers with fixed widths (uint32, int64, and so on) rather than native int when the bytes leave your process.

