Convert string to integer type in Go?

前端 未结 5 1967
误落风尘
误落风尘 2020-11-30 19:12

I\'m trying to convert a string returned from flag.Arg(n) to an int. What is the idiomatic way to do this in Go?

相关标签:
5条回答
  • 2020-11-30 19:22

    Here are three ways to parse strings into integers, from fastest runtime to slowest:

    1. strconv.ParseInt(...) fastest
    2. strconv.Atoi(...) still very fast
    3. fmt.Sscanf(...) not terribly fast but most flexible

    Here's a benchmark that shows usage and example timing for each function:

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

    You can run it by saving as atoi_test.go and running 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 讨论(0)
  • 2020-11-30 19:23

    If you control the input data, you can use the mini version

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

    the fastest option (write your check if necessary). Result :

    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
    
    0 讨论(0)
  • 2020-11-30 19:30

    For example,

    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)
    }
    
    0 讨论(0)
  • 2020-11-30 19:30

    Converting Simple strings

    The easiest way is to use the strconv.Atoi() function.

    Note that there are many other ways. For example fmt.Sscan() and strconv.ParseInt() which give greater flexibility as you can specify the base and bitsize for example. Also as noted in the documentation of strconv.Atoi():

    Atoi is equivalent to ParseInt(s, 10, 0), converted to type int.

    Here's an example using the mentioned functions (try it on the 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)
    }
    

    Output (if called with argument "123"):

    i=123, type: int
    i=123, type: int64
    i=123, type: int
    

    Parsing Custom strings

    There is also a handy fmt.Sscanf() which gives even greater flexibility as with the format string you can specify the number format (like width, base etc.) along with additional extra characters in the input string.

    This is great for parsing custom strings holding a number. For example if your input is provided in a form of "id:00123" where you have a prefix "id:" and the number is fixed 5 digits, padded with zeros if shorter, this is very easily parsable like this:

    s := "id:00123"
    
    var i int
    if _, err := fmt.Sscanf(s, "id:%5d", &i); err == nil {
        fmt.Println(i) // Outputs 123
    }
    
    0 讨论(0)
  • 2020-11-30 19:38

    Try this

    import ("strconv")
    
    value : = "123"
    number,err := strconv.ParseUint(value, 10, 32)
    
    0 讨论(0)
提交回复
热议问题