我正在尝试将从flag.Arg(n)返回的字符串转换为int。 Go中惯用的方式是什么?
例如,
package main
import (
"flag"
"fmt"
"os"
"strconv"
)
func main() {
flag.Parse()
s := flag.Arg(0)
// string to int
i, err := strconv.Atoi(s)
if err != nil {
// handle error
fmt.Println(err)
os.Exit(2)
}
fmt.Println(s, i)
}
我可以return 2吗?
func main() { ... }不带参数,也不返回值。 使用os包Exit函数,例如 os.Exit(2).
另外,也可以做一个致命的举动。 panic(err)
转换简单字符串
最简单的方法是使用strconv.Atoi()函数。
请注意,还有许多其他方法。例如,fmt.Sscan()和strconv.ParseInt()提供了更大的灵活性,例如,您可以指定基数和位大小。也如strconv.Atoi()文档中所述:
Atoi is equivalent to ParseInt(s, 10, 0), converted to type int.
这是使用上述功能的示例(在Go Playground上尝试):
flag.Parse()
s := flag.Arg(0)
if i, err := strconv.Atoi(s); err == nil {
fmt.Printf("i=%d, type: %T
", i, i)
}
if i, err := strconv.ParseInt(s, 10, 64); err == nil {
fmt.Printf("i=%d, type: %T
", i, i)
}
var i int
if _, err := fmt.Sscan(s, &i); err == nil {
fmt.Printf("i=%d, type: %T
", i, i)
}
输出(如果使用参数"123"调用):
i=123, type: int
i=123, type: int64
i=123, type: int
解析自定义字符串
还有一个方便的fmt.Sscanf(),它提供了更大的灵活性,因为使用格式字符串,您可以在输入string中指定数字格式(例如宽度,基数等)以及其他额外的字符。
这对于解析包含数字的自定义字符串非常有用。例如,如果以"id:00123"的形式提供输入,其中前缀为"id:",并且数字固定为5位数字,如果较短则用零填充,这很容易解析,如下所示:
s :="id:00123"
var i int
if _, err := fmt.Sscanf(s,"id:%5d", &i); err == nil {
fmt.Println(i) // Outputs 123
}
ParseInt的第二个参数指定什么?
@ kaushik94单击strconv.ParseInt()链接,您将立即看到:ParseInt(s string, base int, bitSize int)。 因此其基数为:" ParseInt解释给定基数(2到36)中的字符串s"
请注意,strconv.ParseInt()的bitSize参数不会将字符串转换为您选择的类型,而只是在此处将结果限制为特定的位数。 另请参阅:stackoverflow.com/questions/55925894/
@viv是的,那是正确的。 如果需要类型int的值并且使用了strconv.ParseInt(),则需要手动类型转换(从int64到int)。
以下是将字符串解析为整数的三种方法,从最快的运行时间到最慢的运行时间:
strconv.ParseInt(...)最快
strconv.Atoi(...)仍然非常快
fmt.Sscanf(...)速度不是很快,但最灵活
这是一个基准测试,显示了每个功能的用法和示例计时:
package main
import"fmt"
import"strconv"
import"testing"
var num = 123456
var numstr ="123456"
func BenchmarkStrconvParseInt(b *testing.B) {
num64 := int64(num)
for i := 0; i < b.N; i++ {
x, err := strconv.ParseInt(numstr, 10, 64)
if x != num64 || err != nil {
b.Error(err)
}
}
}
func BenchmarkAtoi(b *testing.B) {
for i := 0; i < b.N; i++ {
x, err := strconv.Atoi(numstr)
if x != num || err != nil {
b.Error(err)
}
}
}
func BenchmarkFmtSscan(b *testing.B) {
for i := 0; i < b.N; i++ {
var x int
n, err := fmt.Sscanf(numstr,"%d", &x)
if n != 1 || x != num || err != nil {
b.Error(err)
}
}
}
您可以通过另存为atoi_test.go并运行go test -bench=. atoi_test.go来运行它。
goos: darwin
goarch: amd64
BenchmarkStrconvParseInt-8 100000000 17.1 ns/op
BenchmarkAtoi-8 100000000 19.4 ns/op
BenchmarkFmtSscan-8 2000000 693 ns/op
PASS
ok command-line-arguments 5.797s
尝试这个
import ("strconv")
value : ="123"
number,err := strconv.ParseUint(value, 10, 32)
如果您控制输入数据,则可以使用迷你版
package main
import (
"testing"
"strconv"
)
func Atoi (s string) int {
var (
n uint64
i int
v byte
)
for ; i < len(s); i++ {
d := s[i]
if '0' <= d && d <= '9' {
v = d - '0'
} else if 'a' <= d && d <= 'z' {
v = d - 'a' + 10
} else if 'A' <= d && d <= 'Z' {
v = d - 'A' + 10
} else {
n = 0; break
}
n *= uint64(10)
n += uint64(v)
}
return int(n)
}
func BenchmarkAtoi(b *testing.B) {
for i := 0; i < b.N; i++ {
in := Atoi("9999")
_ = in
}
}
func BenchmarkStrconvAtoi(b *testing.B) {
for i := 0; i < b.N; i++ {
in, _ := strconv.Atoi("9999")
_ = in
}
}
最快的选择(如有必要,写上您的支票)。结果:
Path>go test -bench=. atoi_test.go
goos: windows
goarch: amd64
BenchmarkAtoi-2 100000000 14.6 ns/op
BenchmarkStrconvAtoi-2 30000000 51.2 ns/op
PASS
ok path 3.293s
什么 ? 真的吗 写" go"的人变得很容易。 不要旋转轮子:)
那Atoi("-9999")呢?