In Go, we usually expect reasonable performance and brevity. For example, package main import ( "encoding/hex" "fmt" "math/big" "regexp" "strings" ) func formatSerial(serial *big.Int) string { b := serial.Bytes() buf := make([]byte, 0, 3*len(b)) x := buf[1*len(b) : 3*len(b)] hex.Encode(x, b) for i := 0; i < len(x); i += 2 { buf = append(buf, x[i], x[i+1], ':') } return string(buf[:len(buf)-1]) } func main() { fmt.Println(formatSerial(big.NewInt(1234))) // "04:d2" fmt.Println(formatSerial(big.NewInt(123456))) // "01:e2:40" fmt.Println(formatSerial(big.NewInt(1234567891011121314))) // "11:22:10:f4:b2:d2:30:a2" } Output: 04:d2 01:e2:40 11:22:10:f4:b2:d2:30:a2 Benchmark: `serial := big.NewInt(1234567891011121314)`: BenchmarkPeterSO 3000000 552 ns/op 72 B/op 3 allocs/op BenchmarkKissgyorgy 500000 2545 ns/op 120 B/op 7 allocs/op Benchmark200Success 30000 40675 ns/op 40675 B/op 35 allocs/op