ChatGPT解决这个技术问题 Extra ChatGPT

Convert string to integer type in Go?

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?

strconv.Itoa(i) (int to ASCII) to set an int to a string. See stackoverflow.com/a/62737936/12817546. strconv.Atoi(s) (ASCII to int) to set a string to an int. See stackoverflow.com/a/62740786/12817546.

b
blackgreen

For example strconv.Atoi.

Code:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    s := "123"

    // string to int
    i, err := strconv.Atoi(s)
    if err != nil {
        // ... handle error
        panic(err)
    }

    fmt.Println(s, i)
}

strconv can be interpreted as String Convert likewise, is there any meaning (extension) for Atoi to make it easier to remember.
@RoshanaPitigala "A" as in A-to-Z for the alphabet which is represented by strings. And then "i" for integer. A to i. That's one way. Another way is to know the origin of "atoi" which is apparently "ASCII to integer": stackoverflow.com/a/2909772/1544473
i
icza

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
}

What does the second argument to ParseInt specify?
@kaushik94 Click on the strconv.ParseInt() link and you'll see immediately: ParseInt(s string, base int, bitSize int). So it's the base: "ParseInt interprets a string s in the given base (2 to 36) "
Note that the bitSize argument to strconv.ParseInt() will not convert the string to your choice of type but instead is only there to confine the result to a specific 'bitness'. See also: stackoverflow.com/questions/55925894/…
@viv Yes, that's correct. If a value of type int is required and strconv.ParseInt() is used, manual type conversion is needed (from int64 to int).
P
Pallav Agarwal

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

strconv.ParseInt(...) fastest strconv.Atoi(...) still very fast 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

Clear and helpful answer. I quoted you here stackoverflow.com/a/62740786/12817546.
Atoi is equivalent to ParseInt(s, 10, 0), converted to type int. pkg.go.dev/strconv#Atoi
M
MD.Mahedi hasan

Try this

import ("strconv")

value := "123"
number,err := strconv.ParseUint(value, 10, 32)
finalIntNum := int(number) //Convert uint64 To int

This code will silently (no error) transform values which are in the uint32 range but not in the int range on platforms where int is 32 bits. Example value: "4234567890" is converted to -60399406. Go Playground (64 bits)
J
Jenyokcoder

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

What ? Really ? People who wrote "go" made a lot easy. Dont spin your wheel :)
What about Atoi("-9999")?
This implementation lacks documentation that would mentions the not handled edge cases (ex: negative decimal integers). And I'm not even mentioning the lack of tests.