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?

- 389,944
- 63
- 907
- 827

- 112,946
- 110
- 377
- 526
-
8`strconv.Itoa(i)` (int to ASCII) to set an int to a string. See https://stackoverflow.com/a/62737936/12817546. `strconv.Atoi(s)` (ASCII to int) to set a string to an int. See https://stackoverflow.com/a/62740786/12817546. – Jul 09 '20 at 09:05
5 Answers
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)
}

- 34,072
- 23
- 111
- 129

- 158,998
- 31
- 281
- 276
-
2`strconv` can be interpreted as _String Convert_ likewise, is there any meaning (extension) for `Atoi` to make it easier to remember. – Roshana Pitigala Jun 13 '21 at 17:19
-
9@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 – Adé Jun 20 '21 at 02:59
-
2It is a shame that in a language created WELL into the era of UNICODE, the best mnemonic the creators of Go could think of were "Alphabet-to-Integer" (which is misleading; decimal digits are not alphabet characters) or "ASCII-to-Integer" (which is obsolete and will someday soon be remanded to the dustbin of history). "Character-to-Integer", "String-to-Integer", or even "Unicode-to-Integer" would have been MUCH better mnemonics, IMO. On reflection it seems like they were just mimicking the C language convention which includes an `atoi()` library function. – BalRog Oct 26 '22 at 14:13
-
Of course they would mimick the C language convention. This is a good practice, it follows the principle of least surprise. – MarioVilas Apr 21 '23 at 09:59
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
}

- 389,944
- 63
- 907
- 827
-
-
2@kaushik94 Click on the [`strconv.ParseInt()`](https://golang.org/pkg/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) "_ – icza May 27 '16 at 01:19
-
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: https://stackoverflow.com/questions/55925894/parseint-doesnt-convert-to-the-desired-type/55926193 – viv Jun 24 '19 at 04:35
-
@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`). – icza Jun 24 '19 at 08:36
Here are three ways to parse strings into integers, from fastest runtime to slowest:
strconv.ParseInt(...)
fasteststrconv.Atoi(...)
still very fastfmt.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

- 108
- 10

- 151,642
- 46
- 269
- 291
-
Clear and helpful answer. I quoted you here https://stackoverflow.com/a/62740786/12817546. – Jul 07 '20 at 09:00
-
1`Atoi is equivalent to ParseInt(s, 10, 0), converted to type int.` https://pkg.go.dev/strconv#Atoi – gondo Apr 29 '22 at 16:44
Try this
import ("strconv")
value := "123"
number,err := strconv.ParseUint(value, 10, 32)
finalIntNum := int(number) //Convert uint64 To int

- 102
- 1
- 5
-
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)](https://go.dev/play/p/C7znby6qyvF) – dolmen Jun 01 '22 at 17:31
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

- 31
- 3
-
1What ? Really ? People who wrote "go" made a lot easy. Dont spin your wheel :) – Balaji Boggaram Ramanarayan Apr 30 '18 at 18:19
-
-
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. – dolmen Jun 01 '22 at 17:36
-
1If anybody is tempted to use this despite the comments above be aware that the base is hardcoded to 10 but it decodes letters as if it were an arbitrary base. This will give strange results if you try to decode hex with it. – Andrew Sep 20 '22 at 07:36
-
A correct benchmark would include all kinds of numbers to see whether there is a difference between decimals and hex. Also hex. is limited to 'F' (not 'Z') and requires 'n *= 16' not 10... – Alexis Wilke Mar 16 '23 at 18:12