web-dev-qa-db-fra.com

Convertir une chaîne en type entier dans Go?

J'essaie de convertir une chaîne renvoyée de flag.Arg(n) en int. Quelle est la manière idiomatique de faire cela dans Go?

191
Matt Joiner

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

Conversion de chaînes simples

Le moyen le plus simple consiste à utiliser la fonction strconv.Atoi() .

Notez qu'il existe de nombreuses autres manières. Par exemple, les commandes fmt.Sscan() et strconv.ParseInt() offrent une plus grande souplesse dans la mesure où vous pouvez spécifier la base et la taille en bits, par exemple. Aussi, comme indiqué dans la documentation de strconv.Atoi():

Atoi est un raccourci pour ParseInt (s, 10, 0).

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 l'argument "123"):

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

Analyse de chaînes personnalisées

Il existe également un utilitaire fmt.Sscanf() qui offre une flexibilité encore plus grande, car vous pouvez spécifier le format du numéro (comme la largeur, la base, etc.) ainsi que des caractères supplémentaires dans la variable string.

C'est parfait pour analyser des chaînes personnalisées contenant un numéro. Par exemple, si votre entrée est fournie sous la forme "id:00123" où vous avez un préfixe "id:" et que le nombre est fixé à 5 chiffres, complétée par des zéros si elle est plus courte, ceci 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
}
44
icza

Voici trois manières d’analyser des chaînes en entiers, du plus rapide au plus lent:

  1. strconv.ParseInt(...) le plus rapide
  2. strconv.Atoi(...) toujours très rapide
  3. fmt.Sscanf(...) Pas très rapide mais très flexible

Voici un point de repère qui montre l’utilisation et un exemple de minutage 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 en tant que 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
11
maerics

Essaye ça

import ("strconv")

value : = "123"
number,err := strconv.ParseUint(value, 10, 32)
0
MD.Mahedi hasan

Si vous contrôlez les données d'entrée, vous pouvez utiliser la version mini

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 (faites 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
0
Jenyokcoder