Convertire la stringa in tipo intero in Vai?


236

Sto cercando di convertire una stringa restituita da flag.Arg(n)a int. Qual è il modo idiomatico per farlo in Go?

Risposte:


298

Per esempio,

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

14
func main() { ... }non accetta argomenti e non restituisce alcun valore. Utilizzare la funzione di ospacchetto Exit, ad es.os.Exit(2).
peterSO,

2
In alternativa, basta fare un fatale esempiopanic(err)
Peter Bengtsson

70

Conversione di stringhe semplici

Il modo più semplice è utilizzare la strconv.Atoi()funzione.

Nota che ci sono molti altri modi. Ad esempio fmt.Sscan()e strconv.ParseInt()che offrono una maggiore flessibilità, come ad esempio è possibile specificare la base e la dimensione dei bit. Inoltre, come indicato nella documentazione di strconv.Atoi():

Atoi è equivalente a ParseInt (s, 10, 0), convertito in tipo int.

Ecco un esempio usando le funzioni menzionate (provalo sul 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 (se chiamato con argomento "123"):

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

Analisi di stringhe personalizzate

C'è anche un utile fmt.Sscanf()che offre una flessibilità ancora maggiore poiché con la stringa di formato è possibile specificare il formato numerico (come larghezza, base ecc.) Insieme a caratteri aggiuntivi aggiuntivi nell'input string.

Questo è ottimo per analizzare stringhe personalizzate che contengono un numero. Ad esempio, se il tuo input viene fornito in una forma in "id:00123"cui hai un prefisso "id:"e il numero è fisso a 5 cifre, riempito con zeri se più corto, questo è facilmente analizzabile in questo modo:

s := "id:00123"

var i int
if _, err := fmt.Sscanf(s, "id:%5d", &i); err == nil {
    fmt.Println(i) // Outputs 123
}

Qual è il secondo argomento da ParseIntspecificare?
kaushik94,

1
@ kaushik94 Clicca sul strconv.ParseInt()link e vedrete subito: ParseInt(s string, base int, bitSize int). Quindi è la base: "ParseInt interpreta una stringa s nella base data (da 2 a 36)"
icza,

Si noti che l'argomento bitSize in strconv.ParseInt () non converte la stringa nella scelta del tipo, ma è solo lì per limitare il risultato a uno specifico 'testimone'. Vedi anche: stackoverflow.com/questions/55925894/…
viv

@viv Sì, è corretto. Se intè necessario ed strconv.ParseInt()è utilizzato un valore di tipo, è necessaria la conversione manuale del tipo (da int64a int).
Icza,

16

Ecco tre modi per analizzare le stringhe in numeri interi, dal runtime più veloce al più lento:

  1. strconv.ParseInt(...) più veloce
  2. strconv.Atoi(...) ancora molto veloce
  3. fmt.Sscanf(...) non terribilmente veloce ma più flessibile

Ecco un benchmark che mostra i tempi di utilizzo e di esempio per ciascuna funzione:

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

Puoi eseguirlo salvando come atoi_test.goed eseguendo 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

2

Prova questo

import ("strconv")

value : = "123"
number,err := strconv.ParseUint(value, 10, 32)

0

Se controlli i dati di input, puoi utilizzare la versione 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'opzione più veloce (scrivere l'assegno se necessario). Risultato:

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

1
Che cosa ? Veramente ? Le persone che hanno scritto "go" hanno reso le cose molto facili. Non girare la ruota :)
Balaji Boggaram Ramanarayan,

Che dire di Atoi ("- 9999")?
Oleksiy Chechel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.