Golang strconv.AppendFloat
最后修改于 2025 年 4 月 20 日
本教程将解释如何在 Go 中使用 strconv.AppendFloat 函数。我们将通过实际示例介绍浮点数到字符串转换的基础知识。
strconv.AppendFloat 函数将浮点数转换为字符串并将其附加到字节切片。它提供对格式的精确控制。
AppendFloat 对于构建包含浮点数值的字符串非常高效,因为它通过直接附加到现有字节切片来避免分配。它支持各种格式选项和精度。
基本的 strconv.AppendFloat 示例
strconv.AppendFloat 最简单的用法是将浮点数转换为字符串并将其附加到字节切片。这里我们展示了基本用法。
package main
import (
"fmt"
"strconv"
)
func main() {
buf := []byte("Value: ")
f := 3.14159
buf = strconv.AppendFloat(buf, f, 'f', 2, 64)
fmt.Println(string(buf))
}
我们从包含 "Value: " 的字节切片开始,然后附加一个格式化的浮点数。'f' 格式指定了定点表示法,并带有 2 位小数。
不同的格式选项
strconv.AppendFloat 支持多种格式选项。此示例演示了 'f'、'e'、'g' 和 'b' 格式。
package main
import (
"fmt"
"strconv"
)
func main() {
f := 1234.5678
fmt.Println(string(strconv.AppendFloat([]byte{}, f, 'f', 2, 64)))
fmt.Println(string(strconv.AppendFloat([]byte{}, f, 'e', 2, 64)))
fmt.Println(string(strconv.AppendFloat([]byte{}, f, 'g', 4, 64)))
fmt.Println(string(strconv.AppendFloat([]byte{}, f, 'b', -1, 64)))
}
每种格式会产生不同的输出:'f' 用于定点数,'e' 用于科学计数法,'g' 用于紧凑表示,'b' 用于二进制指数。
控制精度
精度参数控制显示多少位数。此示例显示了同一浮点数的不同精度值。
package main
import (
"fmt"
"strconv"
)
func main() {
f := 3.141592653589793
for _, prec := range []int{0, 2, 4, 6, 8} {
buf := strconv.AppendFloat([]byte("π ≈ "), f, 'f', prec, 64)
fmt.Println(string(buf))
}
}
我们以递增的精度级别展示 π。更高的精度值会在输出中显示更多的小数位数。
构建复杂字符串
AppendFloat 有助于高效地构建复杂字符串。此示例创建了一个格式化的测量字符串。
package main
import (
"fmt"
"strconv"
)
func main() {
temp := 23.456
humidity := 45.678
buf := []byte("Current conditions: ")
buf = strconv.AppendFloat(buf, temp, 'f', 1, 64)
buf = append(buf, "°C, "...)
buf = strconv.AppendFloat(buf, humidity, 'f', 1, 64)
buf = append(buf, "% humidity"...)
fmt.Println(string(buf))
}
我们通过附加多个浮点数值和文本来构建天气报告字符串。与字符串拼接相比,这种方法可以最大限度地减少分配。
处理特殊的浮点数值
AppendFloat 可以正确处理 NaN 和无穷大等特殊浮点数值。此示例演示了它们的字符串表示。
package main
import (
"fmt"
"math"
"strconv"
)
func main() {
values := []float64{
math.NaN(),
math.Inf(1),
math.Inf(-1),
0.0,
}
for _, v := range values {
buf := strconv.AppendFloat([]byte{}, v, 'g', -1, 64)
fmt.Println(string(buf))
}
}
特殊浮点数值会被转换为它们的字符串表示:“NaN”表示非数字,“+Inf”表示正无穷大,“-Inf”表示负无穷大。
性能比较
此示例比较了 AppendFloat 与 fmt.Sprintf 在浮点数到字符串转换性能上的差异。
package main
import (
"fmt"
"strconv"
"time"
)
func main() {
const iterations = 1000000
f := 123.456789
// Benchmark AppendFloat
start := time.Now()
buf := make([]byte, 0, 32)
for i := 0; i < iterations; i++ {
buf = strconv.AppendFloat(buf[:0], f, 'f', 2, 64)
}
fmt.Println("AppendFloat duration:", time.Since(start))
// Benchmark Sprintf
start = time.Now()
for i := 0; i < iterations; i++ {
_ = fmt.Sprintf("%.2f", f)
}
fmt.Println("Sprintf duration:", time.Since(start))
}
AppendFloat 在浮点数格式化方面比 fmt.Sprintf 快得多,尤其是在性能关键的代码中构建字符串时。
实际示例:CSV 生成
这个实际示例演示了如何使用 AppendFloat 高效地生成包含浮点数值的 CSV 数据。
package main
import (
"fmt"
"strconv"
)
type Measurement struct {
Time float64
Value float64
}
func main() {
data := []Measurement{
{0.0, 12.3},
{1.0, 15.6},
{2.0, 18.2},
{3.0, 22.1},
}
var csv []byte
csv = append(csv, "time,value\n"...)
for _, m := range data {
csv = strconv.AppendFloat(csv, m.Time, 'f', 1, 64)
csv = append(csv, ',')
csv = strconv.AppendFloat(csv, m.Value, 'f', 1, 64)
csv = append(csv, '\n')
}
fmt.Println(string(csv))
}
我们通过将浮点数值直接附加到字节切片来生成 CSV 输出。这种方法在内存方面效率很高,并避免了不必要的字符串分配。
来源
本教程通过各种场景下的浮点数到字符串转换的实际示例,涵盖了 Go 中的 strconv.AppendFloat 函数。