J'essaie de convertir une chaîne renvoyée par flag.Arg(n)
un int
. Quelle est la façon idiomatique de le faire dans Go?
J'essaie de convertir une chaîne renvoyée par flag.Arg(n)
un int
. Quelle est la façon idiomatique de le faire dans Go?
Réponses:
Par exemple,
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)
}
panic(err)
La façon la plus simple est d'utiliser la strconv.Atoi()
fonction.
Notez qu'il existe de nombreuses autres façons. Par exemple fmt.Sscan()
et strconv.ParseInt()
qui offrent une plus grande flexibilité car vous pouvez spécifier la base et la taille des bits par exemple. Aussi, comme indiqué dans la documentation de strconv.Atoi()
:
Atoi est équivalent à ParseInt (s, 10, 0), converti en type int.
Voici un exemple utilisant les fonctions mentionnées (essayez-le sur le 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)
}
Sortie (si appelée avec argument "123"
):
i=123, type: int
i=123, type: int64
i=123, type: int
Il y a aussi un fmt.Sscanf()
qui donne encore plus de flexibilité car avec la chaîne de format, vous pouvez spécifier le format numérique (comme la largeur, la base, etc.) ainsi que des caractères supplémentaires supplémentaires dans l'entrée string
.
C'est idéal pour analyser des chaînes personnalisées contenant un nombre. Par exemple, si votre entrée est fournie sous la forme d' "id:00123"
un préfixe "id:"
et que le nombre est fixé à 5 chiffres, complété par des zéros si plus court, c'est très facilement analysable comme ceci:
s := "id:00123"
var i int
if _, err := fmt.Sscanf(s, "id:%5d", &i); err == nil {
fmt.Println(i) // Outputs 123
}
ParseInt
préciser?
strconv.ParseInt()
lien et vous verrez immédiatement: ParseInt(s string, base int, bitSize int)
. C'est donc la base: "ParseInt interprète une chaîne s dans la base donnée (2 à 36)"
int
est requise et strconv.ParseInt()
utilisée, une conversion de type manuelle est nécessaire (de int64
à int
).
Voici trois façons d'analyser des chaînes en nombres entiers, de l'exécution la plus rapide à la plus lente:
strconv.ParseInt(...)
le plus rapidestrconv.Atoi(...)
toujours très rapidefmt.Sscanf(...)
pas terriblement rapide mais plus flexibleVoici un benchmark qui montre l'utilisation et un exemple de synchronisation pour chaque fonction:
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)
}
}
}
Vous pouvez l'exécuter en enregistrant sous atoi_test.go
et en exécutant 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
Essaye ça
import ("strconv")
value : = "123"
number,err := strconv.ParseUint(value, 10, 32)
Si vous contrôlez les données d'entrée, vous pouvez utiliser la 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
}
}
l'option la plus rapide (écrivez votre chèque si nécessaire). Résultat :
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
func main() { ... }
ne prend aucun argument et ne renvoie aucune valeur. Utilisez la fonction deos
packageExit
par exempleos.Exit(2).