2017-10-21 07:06

# 将int转换为十六进制字符串，然后在Golang中用0填充的有效方法？

I'm trying to convert 10 millions of int to Hex, then, padding it with 0's in order to get a 4 characters string which represents the Hex number.

So far, I tried the following:

``````var hexNumber string
for idx := O; idx < 10000000; idx++ {
hexNumber = fmt.Sprintf("%04x", idx)

// Do some stuff ....
}
``````

But `fmt.Sprintf` is not very efficient. How can I achieve this in a efficient way?

Solution: It turns out that @peterSO `strconv.AppendInt` solution is way faster.

``````package bench

import (
"fmt"
"strconv"
"strings"
"testing"
)

var stringHex [16]string
var runesHex [16]rune

func init() {
stringHex = [16]string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}
runesHex = [16]rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}
}

func intToHex1(intNumber int) string {
hexNumber := []rune("0000")
for i, j := int(0), uint(12); i < 4; i, j = i+1, j-4 {
hexNumber[i] = runesHex[(intNumber>>j)&0x0f]
}
return string(hexNumber)
}

func intToHex2(intNumber int) string {
hexNumber := "0000"
for i, j := int(0), uint(12); i < 4; i, j = i+1, j-4 {
hexNumber = hexNumber[:i] + stringHex[(intNumber>>j)&0x0f] + hexNumber[i+1:]
}
return hexNumber
}

func BenchmarkFmtSprintf(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
hexNumber := fmt.Sprintf("%04x", n)
_ = hexNumber
}
}

func BenchmarkStrconvFormatInt(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
retStr := strings.Repeat("0", 4) + strconv.FormatInt(int64(n), 16)
hexNumber := retStr[(len(retStr) - 4):]
_ = hexNumber
}
}

func BenchmarkAppend(b *testing.B) {
b.ReportAllocs()
buf := []byte{'0', '0', '0', '0', 4 + 16: 0}
for n := 0; n < b.N; n++ {
buf = strconv.AppendInt(buf[:4], int64(n), 16)
hexNumber := string(buf[len(buf)-4:])
_ = hexNumber
}
}

func BenchmarkIntToHex1(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
hexNumber := intToHex1(n)
_ = hexNumber
}
}

func BenchmarkIntToHex2(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
hexNumber := intToHex2(n)
_ = hexNumber
}
}
``````

So the benchmark:

``````BenchmarkFmtSprintf-2            3000000               364 ns/op              16 B/op          2 allocs/op
BenchmarkStrconvFormatInt-2      5000000               354 ns/op              15 B/op          3 allocs/op
BenchmarkAppend-2               20000000                75.6 ns/op             0 B/op          0 allocs/op
BenchmarkIntToHex1-2            10000000               162 ns/op               8 B/op          1 allocs/op
BenchmarkIntToHex2-2             3000000               536 ns/op              16 B/op          4 allocs/op
``````
• 写回答
• 好问题 提建议
• 关注问题
• 收藏
• 邀请回答

#### 2条回答默认 最新

• dongshanxiao7328 2017-10-21 09:09
已采纳

`strconv.AppendUint` appears to be faster than `fmt.Sprintf`. For example,

`hex_test.go`:

``````package main

import (
"fmt"
"strconv"
"testing"
)

func BenchmarkFmtSprintf(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
hexNumber := fmt.Sprintf("%04x", n&0xFFFF)
_ = hexNumber
}
}

func BenchmarkAppend(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
buf := []byte{'0', '0', '0', 3 + 4: 0}
buf = strconv.AppendUint(buf[:3], uint64(n)&0xFFFF, 16)
hexNumber := string(buf[len(buf)-4:])
_ = hexNumber // Do some stuff ....
}
}
``````

Output:

``````\$ go test -bench=. hex_test.go
BenchmarkSprintf-4      10000000       116 ns/op      16 B/op     1 allocs/op
BenchmarkAppend-4       100000000       19.2 ns/op     0 B/op     0 allocs/op
``````
已采纳该答案
评论
解决 无用
打赏 举报
• dpxyfa4718 2017-10-21 07:56

You should be able to use strconv, then just pad manually. This probably does less work.

``````strconv.FormatInt(idx,16)
``````
评论
解决 无用
打赏 举报