Zeichenfolge in Ganzzahl in Go konvertieren?

235

Ich versuche, eine zurückgegebene Zeichenfolge flag.Arg(n)in eine zu konvertieren int. Was ist der idiomatische Weg, dies in Go zu tun?

Matt Joiner
quelle

Antworten:

298

Beispielsweise,

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)
}
peterSO
quelle
14
func main() { ... }Nimmt keine Argumente und gibt keinen Wert zurück. Verwenden Sie die osPaket - ExitFunktion zBos.Exit(2).
peterSO
2
Alternativ machen Sie einfach ein tödliches Egpanic(err)
Peter Bengtsson
70

Einfache Zeichenfolgen konvertieren

Am einfachsten ist es, die strconv.Atoi()Funktion zu verwenden.

Beachten Sie, dass es viele andere Möglichkeiten gibt. Zum Beispiel fmt.Sscan()und strconv.ParseInt()die eine größere Flexibilität bieten, da Sie beispielsweise die Basis und die Bitgröße angeben können. Auch wie in der Dokumentation von strconv.Atoi():

Atoi entspricht ParseInt (s, 10, 0) und wird in den Typ int konvertiert.

Hier ist ein Beispiel mit den genannten Funktionen (probieren Sie es auf dem Go Playground aus ):

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

Ausgabe (wenn mit Argument aufgerufen "123"):

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

Benutzerdefinierte Zeichenfolgen analysieren

Es gibt auch eine praktische Funktion, fmt.Sscanf()die noch mehr Flexibilität bietet, da Sie mit der Formatzeichenfolge das Zahlenformat (wie Breite, Basis usw.) zusammen mit zusätzlichen zusätzlichen Zeichen in der Eingabe angeben können string.

Dies ist ideal zum Parsen von benutzerdefinierten Zeichenfolgen, die eine Zahl enthalten. Wenn Ihre Eingabe beispielsweise in einer Form erfolgt, in der "id:00123"Sie ein Präfix haben "id:"und die Zahl auf 5 Stellen festgelegt ist, die mit Nullen aufgefüllt sind, wenn sie kürzer sind, kann dies sehr einfach wie folgt analysiert werden:

s := "id:00123"

var i int
if _, err := fmt.Sscanf(s, "id:%5d", &i); err == nil {
    fmt.Println(i) // Outputs 123
}
icza
quelle
Was ist das zweite Argument zu ParseIntspezifizieren?
Kaushik94
1
@ kaushik94 Klicken Sie auf den strconv.ParseInt()Link und Sie sehen sofort : ParseInt(s string, base int, bitSize int). Es ist also die Basis: "ParseInt interpretiert einen String s in der angegebenen Basis (2 bis 36)"
icza
Beachten Sie, dass das bitSize-Argument in strconv.ParseInt () die Zeichenfolge nicht in den von Ihnen gewählten Typ konvertiert, sondern nur dazu dient, das Ergebnis auf eine bestimmte 'Bitness' zu beschränken. Siehe auch: stackoverflow.com/questions/55925894/…
viv
@viv Ja, das stimmt. Wenn ein Wert vom Typ interforderlich ist und strconv.ParseInt()verwendet wird, ist eine manuelle Typkonvertierung erforderlich (von int64nach int).
icza
16

Hier sind drei Möglichkeiten, um Zeichenfolgen in Ganzzahlen zu analysieren, von der schnellsten bis zur langsamsten Laufzeit:

  1. strconv.ParseInt(...) am schnellsten
  2. strconv.Atoi(...) immer noch sehr schnell
  3. fmt.Sscanf(...) nicht besonders schnell, aber am flexibelsten

Hier ist ein Benchmark, der die Verwendung und das Beispiel-Timing für jede Funktion zeigt:

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

Sie können es ausführen, indem Sie es speichern atoi_test.gound ausführen 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
Maerics
quelle
2

Versuche dies

import ("strconv")

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

Wenn Sie die Eingabedaten steuern, können Sie die Mini-Version verwenden

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

die schnellste Option (schreiben Sie Ihren Scheck, falls erforderlich). Ergebnis:

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
Jenyokcoder
quelle
1
Was? Ja wirklich ? Leute, die "go" geschrieben haben, haben es sehr einfach gemacht.
Drehen Sie nicht
Was ist mit Atoi ("- 9999")?
Oleksiy Chechel