Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

kaatinga/strconv

Repository files navigation

CodeQL GitHub release MIT license codecov Go Tests help wanted

faststrconv

A small, dependency-free package with allocation-light helpers for converting between string, []byte and unsigned integer types (byte, uint16, uint32, uint64).

It is built for the hot path: parsing is ×ばつ faster than the standard library with zero allocations, and the integer → []byte converters are faster than strconv.AppendUint while allocating an exactly-sized slice.

Generics are used for the type-parametrised helpers, so the package requires Go 1.18+.

import faststrconv "github.com/kaatinga/strconv"

Benchmarks

All numbers below are ns/op (lower is better) and B/op from go test -bench=. -benchmem, best of 8 runs on:

goos: darwin goarch: arm64 cpu: Apple M1 go: 1.26

Methodology note: inputs are read from mutable variables and results are stored in package-level sinks, otherwise the compiler constant-folds the calls and escape analysis removes the allocations — which is why naive micro-benchmarks of this kind tend to report a misleading 0 ns/op, 0 allocs/op. The benchmarks live in benchmark_test.go and are paired with the closest strconv equivalent over identical inputs.

Parsing: string / []byte → integer

GetByte, GetUint16 and GetUint32 are a faster, allocation-free alternative to strconv.ParseUint / strconv.Atoi.

Function faststrconv strconv.ParseUint Speed-up
byte GetByte 2.6 ns, 0 B 6.0 ns, 0 B ×ばつ
uint16 GetUint16 3.2 ns, 0 B 8.1 ns, 0 B ×ばつ
uint32 GetUint32 4.8 ns, 0 B 10.1 ns, 0 B ×ばつ

All three accept both string and []byte input (generic over ~string | ~[]byte) and never allocate.

Formatting: integer → []byte

The *2Bytes helpers return a fresh, exactly-sized slice. The closest standard library equivalent is strconv.AppendUint(nil, x, 10).

Function faststrconv strconv.AppendUint(nil, ...)
Byte2Bytes 10.0 ns, 2 B 26 ns, 12 B
Uint162Bytes 12.4 ns, 4 B 26 ns, 12 B
Uint322Bytes 15.0 ns, 8 B 26 ns, 12 B
Uint642Bytes 19.1 ns, 10 B 26 ns, 12 B
Uint2Bytes 19.3 ns, 10 B 26 ns, 12 B

Every converter is both faster and lighter on memory, and the returned slice is trimmed to the exact digit count (no oversized backing array).

Formatting: integer → string

Function faststrconv strconv (FormatUint/Itoa)
Byte2String 9.5 ns, 2 B 15–17 ns
Uint162String 12.2 ns, 2 B 15–17 ns
Uint322String 24.8 ns, 12 B ~17 ns
Uint642String 29.5 ns, 18 B ~17 ns

For byte and uint16 the string converters comfortably beat the standard library. For uint32/uint64, strconv.FormatUint is competitive because it keeps an internal cache of small-integer strings; if you need the fastest path for large integers, prefer the *2Bytes converters above (or strconv directly).

API

Parsing

b, err := faststrconv.GetByte("255") // byte
u16, err := faststrconv.GetUint16("64555") // uint16
u32, err := faststrconv.GetUint32("4294967295") // uint32
// Works with []byte too, and with custom types whose underlying type is byte:
v, err := faststrconv.GetCustomByte[string, MyByte]("42")

Formatting

faststrconv.Byte2Bytes(255) // []byte("255")
faststrconv.Uint162Bytes(64555) // []byte
faststrconv.Uint322Bytes(123456) // []byte
faststrconv.Uint642Bytes(123456789)// []byte
faststrconv.Uint2Bytes(uint64(42)) // generic over uint | uint32 | uint64
faststrconv.Byte2String(255) // "255"
faststrconv.Uint162String(64555) // "64555"
faststrconv.Uint322String(123456) // "123456"
faststrconv.Uint642String(123456789)// "123456789"
faststrconv.Uint32And642String(uint64(42)) // generic

Leading zeros

Warning

For the sake of maximum processing speed, the parsers have limited support of leading zeros: the input length cannot exceed the maximum digit length of the target type. For example 012 is accepted for byte, but 0255 is not — it is 4 characters long, which is impossible for a byte value.

If you need to parse a zero-padded number such as 0000000000000255, strip the leading zeros first with the DeleteLeadingZeros helper:

numberINeed, err := faststrconv.GetByte(faststrconv.DeleteLeadingZeros("0000000000000255"))
if err != nil {
	// ...
}

About

Fast and low memory consuming uint to string and string to uint converters

Topics

Resources

Stars

Watchers

Forks

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /