我正在搜索如何将字符串转换为具有最佳性能的二进制字符串表示形式。
所以我从以下类似的东西开始:
func binConvertOrig(s string) string {
var buf bytes.Buffer
for i := 0; i < len(s); i++ {
fmt.Fprintf(&buf, "%08b", s[i])
}
return buf.String()
}
s := "Test"
log.Printf("%s => binConvertOrig => %s", s, binConvertOrig(s))
但似乎是fmt.Fprintf
&amp; bytes.Buffer
效率不高。
有更好的方法吗?
由于
答案 0 :(得分:3)
没有什么比预先计算的查找表更好,特别是如果它存储在切片或数组中(而不是映射中),并且转换器为结果分配一个字节切片,其大小合适: / p>
var byteBinaries [256][]byte
func init() {
for i := range byteBinaries {
byteBinaries[i] = []byte(fmt.Sprintf("%08b", i))
}
}
func strToBin(s string) string {
res := make([]byte, len(s)*8)
for i := len(s) - 1; i >= 0; i-- {
copy(res[i*8:], byteBinaries[s[i]])
}
return string(res)
}
测试它:
fmt.Println(strToBin("\x01\xff"))
输出(在Go Playground上尝试):
0000000111111111
让我们看看它有多快:
var texts = []string{
"\x00",
"123",
"1234567890",
"asdf;lkjasdf;lkjasdf;lkj108fhq098wf34",
}
func BenchmarkOrig(b *testing.B) {
for n := 0; n < b.N; n++ {
for _, t := range texts {
binConvertOrig(t)
}
}
}
func BenchmarkLookup(b *testing.B) {
for n := 0; n < b.N; n++ {
for _, t := range texts {
strToBin(t)
}
}
}
结果:
BenchmarkOrig-4 200000 8526 ns/op 2040 B/op 12 allocs/op
BenchmarkLookup-4 2000000 781 ns/op 880 B/op 8 allocs/op
查找版本(strToBin()
)快11倍并且使用更少的内存和分配。基本上它只使用分配结果(这是不可避免的)。