Created
January 4, 2026 17:27
-
-
Save rluders/bc07cc337ad8c2fa61285d118197707f to your computer and use it in GitHub Desktop.
An idiomatic, high-performance Base62 encoder for uint64 in Go. It avoids string concatenation by using a fixed-size byte buffer, achieving O(n) time complexity with zero heap allocations, and includes clear comments plus a table-driven, TDD-friendly unit test.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package base62 | |
| // base62Chars is the Base62 alphabet. | |
| // Keeping it as a string is fine: it's immutable and indexable. | |
| const base62Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" | |
| // Encode converts a uint64 number into a Base62-encoded string. | |
| func Encode(num uint64) string { | |
| // Special case: | |
| // If the input is 0, return the first character of the alphabet. | |
| // This avoids returning an empty string. | |
| if num == 0 { | |
| return string(base62Chars[0]) | |
| } | |
| // Cache the base (62) once, instead of calling len(...) repeatedly. | |
| const base = uint64(len(base62Chars)) | |
| // A uint64 needs at most 11 Base62 digits: | |
| // 62^10 < 2^64 <= 62^11 | |
| // Using a fixed-size array avoids heap allocations and repeated string concatenations. | |
| var buf [11]byte | |
| // We'll fill the buffer from right to left (most significant digit ends up at the left). | |
| i := len(buf) | |
| for num > 0 { | |
| // Take the next Base62 digit. | |
| rem := num % base | |
| // Write it into the buffer (moving left). | |
| i-- | |
| buf[i] = base62Chars[rem] | |
| // Continue encoding the remaining value. | |
| num /= base | |
| } | |
| // Convert only the used slice of the buffer to a string. | |
| // This avoids O(n^2) behavior from prefix string concatenation in a loop. | |
| return string(buf[i:]) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package base62 | |
| import "testing" | |
| func TestEncode_TableDriven(t *testing.T) { | |
| t.Parallel() | |
| tests := []struct { | |
| name string | |
| in uint64 | |
| want string | |
| }{ | |
| // Start with small, obvious cases (good for TDD red->green). | |
| {"zero", 0, "0"}, | |
| {"one", 1, "1"}, | |
| {"nine", 9, "9"}, | |
| {"ten", 10, "A"}, // 10 maps to 'A' | |
| {"thirty_five", 35, "Z"}, | |
| {"thirty_six", 36, "a"}, | |
| {"sixty_one", 61, "z"}, | |
| // Boundary around 62. | |
| {"sixty_two", 62, "10"}, | |
| {"sixty_three", 63, "11"}, | |
| // A few larger values. | |
| {"one_twenty_three", 123, "1z"}, // 123 = 1*62 + 61 => "1z" | |
| {"three_thousand_eight_hundred_forty_four", 3844, "100"}, // 62^2 | |
| {"max_uint64", ^uint64(0), "LygHa16AHYF"}, // precomputed expected value for this alphabet | |
| } | |
| for _, tc := range tests { | |
| tc := tc // capture range variable | |
| t.Run(tc.name, func(t *testing.T) { | |
| t.Parallel() | |
| got := Encode(tc.in) | |
| if got != tc.want { | |
| t.Fatalf("Encode(%d) = %q; want %q", tc.in, got, tc.want) | |
| } | |
| }) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment