Comments

不要用 fmt.Sprintf 做类型转换

严格的讲,应该是在把 intfloat等类型转换为字符串时,不要用 fmt.Sprintf,更好的做法是用标准库函数。fmt.Sprintf 的用途是格式化字符串,接受的类型是 interface{},内部使用了反射。所以,与相应的标准库函数相比,fmt.Sprintf 需要更大的开销。大多数类型转换的函数都可以在 strconv 包里找到。

int to string

整数类型转换为字符串,推荐使用 strconv.FormatIntint64),对于 int 类型,strconv.Itoa 对前者做了一个封装。

比较一下 strconv.FormatIntfmt.Sprintf 的时间开销:

package main

import (
    "fmt"
    "strconv"
    "time"
)

const LOOP = 10000

var num int64 = 10000

func main() {
    startTime := time.Now()
    for i := 0; i < LOOP; i++ {
        fmt.Sprintf("%d", num)
    }
    fmt.Printf("fmt.Sprintf taken: %v\n", time.Since(startTime))

    startTime = time.Now()
    for i := 0; i < LOOP; i++ {
        strconv.FormatInt(num, 10)
    }
    fmt.Printf("strconv.FormatInt taken: %v\n", time.Since(startTime))
}

其中某一次运行结果:

fmt.Sprintf taken: 2.995178ms
strconv.FormatInt taken: 1.057318ms

多次运行结果都类似,结论是:fmt.Sprintf 所需要的时间大约是 strconv.FormatInt 的 3 倍。

同理,对于 float64 类型,推荐使用 strconv.FormatFloat。测试代码和上面类似,得到的结论是:fmt.Sprintf 所需要的时间大约是 strconv.FormatFloat 的 1.1 倍。效果没有整型明显,但依然更高效。

hexadecimal to string

十六进制数到字符串的转换也很常见,尤其是在一些加解密程序中,如获取 md5 值。 encoding/hex 包提供了十六进制数的编解码函数。

下面比较一下 fmt.Sprintfhex.EncodeToString 的时间开销:

package main

import (
    "crypto/md5"
    "encoding/hex"
    "fmt"
    "io"
    "time"
)

const LOOP = 10000

func makeMd5(data string) []byte {
    h := md5.New()
    io.WriteString(h, data)
    return h.Sum(nil)
}

func main() {
    s := "123456"
    hexBytes := makeMd5(s)
    s1 := fmt.Sprintf("%x", hexBytes)
    s2 := hex.EncodeToString(hexBytes)
    fmt.Println("result of fmt.Sprintf == hex.EncodeToString:", s1 == s2) // 确保结果一致

    start := time.Now()
    for i := 0; i < LOOP; i++ {
        fmt.Sprintf("%x", hexBytes)
    }
    fmt.Printf("fmt.Sprintf taken: %v\n", time.Since(start))

    start = time.Now()
    for i := 0; i < LOOP; i++ {
        hex.EncodeToString(hexBytes)
    }
    fmt.Printf("hex.EncodeToString taken: %v\n", time.Since(start))
}

这个程序某一次的运行结果是:

result of fmt.Sprintf == hex.EncodeToString: true
fmt.Sprintf taken: 10.285488ms
hex.EncodeToString taken: 2.080457ms

多次运行结果都类似,可以得到一个结论:fmt.Sprintf 所需要的时间大约是 hex.EncodeToString 的 5 倍。

这里只讨论了三种数据类型,对于其他类型的数据也是类似的。总之,在需要转换成字符串时,即使对性能要求不高,都尽量不要用 fmt.Sprintf

欢迎关注我的公众号

Comments

getElementsByTagName('BODY')[0]).appendChild(s); }()); getElementsByTagName('BODY')[0]).appendChild(s); }()); getElementsByTagName('BODY')[0]).appendChild(s); }()); comments powered by Disqus ript">comments powered by Disqus.