uhex

package
v1.149.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 13, 2026 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package uhex provides fixed-width, lowercase hexadecimal encoders for unsigned integers and fixed-size byte arrays.

It is intended for hot paths such as trace ID generation, log formatting, and binary protocol work where general-purpose formatting can be unnecessarily expensive. The implementation is deliberately simple: each input byte is mapped through a 256-entry lookup table to its two lowercase hexadecimal characters, which are written with a single 16-bit store.

Compared with generic formatting such as fmt.Sprintf("%x", v), uhex avoids reflection and width handling. Compared with encoding/hex, it focuses on fixed-width values and exposes helpers that write directly into caller-owned arrays.

Output

All encoders produce lowercase hexadecimal.

Integer-based helpers always zero-pad to the full width of the input type:

Byte-array helpers encode each input byte in order, two hex characters per byte:

Allocation Behavior

The slice-returning helpers (Hex64, Hex32, Hex16, Hex8, Hex64B, Hex32B, Hex16B, and Hex8B) are the most convenient API. Each fills a local array (16, 8, 4, or 2 bytes) and returns a slice over it. Whether that array is allocated on the heap depends on escape analysis at the call site:

  • If the returned slice does not escape the caller (for example, it is read and discarded, or only its bytes are consumed), the array stays on the stack and no allocation occurs.
  • If the returned slice escapes (it is stored in a longer-lived structure, returned, sent on a channel, or passed to a function the compiler cannot inline), the backing array is heap-allocated, costing one allocation of the array's width.

For code that must never allocate regardless of escape analysis, prefer the buffer-writing helpers that accept a destination array pointer. Hex64UB, Hex32UB, Hex16UB, and Hex8UB write integer encodings into caller-owned buffers. Hex64BB, Hex32BB, Hex16BB, and Hex8BB do the same for fixed-size byte arrays. These never allocate and, for the 32-bit and narrower widths, are small enough to be inlined into the caller.

Performance

Because every width is known at compile time, the encoders are fully unrolled: there are no loops, no length checks, and no argument validation. Each input byte is translated with a single lookup into a 256-entry table and written with one 16-bit store, so the cost scales linearly with the output width and is independent of the input value (there are no data-dependent branches).

Relative to the standard library and general-purpose formatting, for the small fixed widths this package targets:

  • Against encoding/hex, the buffer-writing helpers are on the order of two to three times faster and, like encoding/hex.Encode, allocate nothing. Part of the gain on the integer helpers is structural: encoding/hex only encodes byte slices, so encoding an integer with it additionally requires serializing the value into a scratch buffer first, whereas the integer helpers here read the value directly.
  • Against fmt.Sprintf("%x", v), the difference is roughly an order of magnitude, and uhex avoids the allocations that reflection-based formatting incurs.
  • When a []byte or string result is returned rather than written into a caller-owned buffer, the single heap allocation for that result dominates the total cost, so the advantage over encoding/hex narrows accordingly; the buffer-writing helpers avoid that allocation entirely.

These are relative characteristics, not guarantees; absolute numbers depend on the hardware and compiler. The package ships benchmarks (run with `go test -bench=.`) so the figures can be reproduced on the target platform.

This package is specialized for small, fixed-width values (up to eight bytes). For arbitrary-length or streaming data, or for decoding, use encoding/hex, which is optimized for those cases; uhex offers no advantage there and does not cover them.

Naming

Function suffixes follow this pattern:

  • No suffix: encode an unsigned integer and return a []byte.
  • UB: encode an unsigned integer into a caller-provided buffer.
  • B: encode a fixed-size byte array and return a []byte.
  • BB: encode a fixed-size byte array into a caller-provided buffer.

Usage

id := uhex.Hex64(traceID)
sum := uhex.Hex32(checksum)
tag := string(uhex.Hex8(kind))

var dst [16]byte
uhex.Hex64UB(traceID, &dst)
out := dst[:]

src := [8]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}
uhex.Hex64BB(src, &dst)

uhex is a good fit when the input width is known in advance and predictable, lowercase, zero-padded hexadecimal output is required.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Hex8

func Hex8(n uint8) []byte

Hex8 returns the zero-padded, lowercase hexadecimal encoding of n as a 2-byte slice.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	h := uhex.Hex8(uint8(128))

	fmt.Println(string(h))

}
Output:
80

func Hex8B

func Hex8B(src [1]byte) []byte

Hex8B returns the lowercase hexadecimal encoding of src as a 2-byte slice.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	h := uhex.Hex8B([1]byte{0xab})

	fmt.Println(string(h))

}
Output:
ab

func Hex8BB

func Hex8BB(src [1]byte, dst *[2]byte)

Hex8BB writes the lowercase hexadecimal encoding of src into dst.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	dst := [2]byte{}
	uhex.Hex8BB([1]byte{0xab}, &dst)

	fmt.Println(string(dst[:]))

}
Output:
ab

func Hex8UB

func Hex8UB(n uint8, dst *[2]byte)

Hex8UB writes the zero-padded, lowercase hexadecimal encoding of n into dst.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	dst := [2]byte{}
	uhex.Hex8UB(uint8(128), &dst)

	fmt.Println(string(dst[:]))

}
Output:
80

func Hex16

func Hex16(n uint16) []byte

Hex16 returns the zero-padded, lowercase hexadecimal encoding of n as a 4-byte slice.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	h := uhex.Hex16(uint16(0xabcd))

	fmt.Println(string(h))

}
Output:
abcd

func Hex16B

func Hex16B(src [2]byte) []byte

Hex16B returns the lowercase hexadecimal encoding of src as a 4-byte slice.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	h := uhex.Hex16B([2]byte{0xab, 0xcd})

	fmt.Println(string(h))

}
Output:
abcd

func Hex16BB

func Hex16BB(src [2]byte, dst *[4]byte)

Hex16BB writes the lowercase hexadecimal encoding of src into dst.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	dst := [4]byte{}
	uhex.Hex16BB([2]byte{0xab, 0xcd}, &dst)

	fmt.Println(string(dst[:]))

}
Output:
abcd

func Hex16UB

func Hex16UB(n uint16, dst *[4]byte)

Hex16UB writes the zero-padded, lowercase hexadecimal encoding of n into dst.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	dst := [4]byte{}
	uhex.Hex16UB(uint16(0xabcd), &dst)

	fmt.Println(string(dst[:]))

}
Output:
abcd

func Hex32

func Hex32(n uint32) []byte

Hex32 returns the zero-padded, lowercase hexadecimal encoding of n as an 8-byte slice.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	h := uhex.Hex32(uint32(0x89abcdef))

	fmt.Println(string(h))

}
Output:
89abcdef

func Hex32B

func Hex32B(src [4]byte) []byte

Hex32B returns the lowercase hexadecimal encoding of src as an 8-byte slice.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	h := uhex.Hex32B([4]byte{0x89, 0xab, 0xcd, 0xef})

	fmt.Println(string(h))

}
Output:
89abcdef

func Hex32BB

func Hex32BB(src [4]byte, dst *[8]byte)

Hex32BB writes the lowercase hexadecimal encoding of src into dst.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	dst := [8]byte{}
	uhex.Hex32BB([4]byte{0x89, 0xab, 0xcd, 0xef}, &dst)

	fmt.Println(string(dst[:]))

}
Output:
89abcdef

func Hex32UB

func Hex32UB(n uint32, dst *[8]byte)

Hex32UB writes the zero-padded, lowercase hexadecimal encoding of n into dst.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	dst := [8]byte{}
	uhex.Hex32UB(uint32(0x89abcdef), &dst)

	fmt.Println(string(dst[:]))

}
Output:
89abcdef

func Hex64

func Hex64(n uint64) []byte

Hex64 returns the zero-padded, lowercase hexadecimal encoding of n as a 16-byte slice.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	h := uhex.Hex64(uint64(0x0123456789abcdef))

	fmt.Println(string(h))

}
Output:
0123456789abcdef

func Hex64B

func Hex64B(src [8]byte) []byte

Hex64B returns the lowercase hexadecimal encoding of src as a 16-byte slice.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	h := uhex.Hex64B([8]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef})

	fmt.Println(string(h))

}
Output:
0123456789abcdef

func Hex64BB

func Hex64BB(src [8]byte, dst *[16]byte)

Hex64BB writes the lowercase hexadecimal encoding of src into dst.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	dst := [16]byte{}
	uhex.Hex64BB([8]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, &dst)

	fmt.Println(string(dst[:]))

}
Output:
0123456789abcdef

func Hex64UB

func Hex64UB(n uint64, dst *[16]byte)

Hex64UB writes the zero-padded, lowercase hexadecimal encoding of n into dst.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/uhex"
)

func main() {
	dst := [16]byte{}
	uhex.Hex64UB(uint64(0x0123456789abcdef), &dst)

	fmt.Println(string(dst[:]))

}
Output:
0123456789abcdef

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL