在Go中将字符串转换为整数类型?


Answers:


298

例如,

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)
}

14
func main() { ... }不带参数也不返回值。使用os打包Exit功能,例如os.Exit(2).
peterSO 2010年

2
另外,也可以做一个致命的举动panic(err)
Peter Bengtsson 2014年

70

转换简单字符串

最简单的方法是使用该strconv.Atoi()功能。

请注意,还有许多其他方法。例如fmt.Sscan()strconv.ParseInt()由于您可以指定基数和位大小,因此可以提供更大的灵活性。也如以下文档中所述strconv.Atoi()

Atoi等效于ParseInt(s,10,0),转换为int类型。

这是使用上述功能的示例(在Go Playground上尝试):

flag.Parse()
s := flag.Arg(0)

if i, err := strconv.Atoi(s); err == nil {
    fmt.Printf("i=%d, type: %T\n", i, i)
}

if i, err := strconv.ParseInt(s, 10, 64); err == nil {
    fmt.Printf("i=%d, type: %T\n", i, i)
}

var i int
if _, err := fmt.Sscan(s, &i); err == nil {
    fmt.Printf("i=%d, type: %T\n", 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 '16

1
@ kaushik94单击strconv.ParseInt()链接,您将立即看到:ParseInt(s string, base int, bitSize int)。因此它是基础:“ ParseInt解释给定基础(2到36)中的字符串s”
icza

请注意,strconv.ParseInt()的bitSize参数不会将字符串转换为您选择的类型,而只是在此处将结果限制为特定的“位”。另请参阅:stackoverflow.com/questions/55925894/…–
viv

@viv是的,这是正确的。如果int需要并strconv.ParseInt()使用类型值,则需要手动类型转换(从int64int)。
icza

16

以下是将字符串解析为整数的三种方法,从最快的运行时间到最慢的运行时间:

  1. strconv.ParseInt(...) 最快的
  2. strconv.Atoi(...) 仍然非常快
  3. 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


0

如果您控制输入数据,则可以使用迷你版

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

1
什么 ?真的吗 写“ go”的人变得很容易。不要旋转轮子:)
Balaji Boggaram Ramanarayan

那Atoi(“-9999”)呢?
Oleksiy Chechel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.