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?

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

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
}

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

2

Versuche dies

import ("strconv")

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

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

1
Was? Ja wirklich ? Leute, die "go" geschrieben haben, haben es sehr einfach gemacht.
Drehen Sie nicht

Was ist mit Atoi ("- 9999")?
Oleksiy Chechel
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.