我有一个uint
as 3123456
,我想得到123456
as 数字(理想情况下uint
),即去掉第一个数字。我知道我可以将其解析为string
,删除前导字符,然后将其转换回来:
func (id *MyID) Scan(v any) (err error) {
asBytes, ok := v.([]byte)
...
myDBNumber := binary.LittleEndian.Uint64(asBytes) // the field is of type BINARY in the db
myDBNumberStr := strconv.Itoa(int(myDBNumber))
myDBNumberWithoutPrefix, err := strconv.Atoi(myDBNumberStr[1:])
...
}
由于我使用这种逻辑来sql.Scanner
解析 ID,我想知道是否有办法避免这种来回解析,以提高性能(或至少比较性能)。
您正在寻找替代方案
我建议计算小于该数字的最大 10 的幂并使用除法余数:
在 Go Playground 上测试一下:
这应该适用于
unit
64 位和 32 位。我不确定使用表格是否真的会提高性能,但您可以轻松尝试使用
powers[c]
而var powers = []uint64{1, 10, 100, ...}
不是e *= 10
:在我的计算机上,基于表格的版本速度略快 (33.37 ns/op vs 35.41 ns/op),因此我更喜欢带有乘法的较慢版本。
您可能想要更改样本数字以匹配您的用例,但是在进行 SQL 调用时您无法识别差异;)
具有字符串解析的版本有 185.2 ns/op(40 B/op、5 allocs/op),因此这可能是一个胜利。
编辑
使用二进制搜索的替代版本:
假设接近均匀分布,这个速度会更快:
不过,在初始基准测试中它的速度较慢
benchmarkValues[i] = uint(r.Intn(1_000_000))
(89.17 ns/op)。它还输给了。