Was ist der Unterschied zwischen int und int64 in Go?

86

Ich habe eine Zeichenfolge, die eine Ganzzahl enthält (die aus einer Datei gelesen wurde).

Ich versuche das stringin ein intusing umzuwandeln strconv.ParseInt(). ParseInterfordert, dass ich eine Bitgröße gebe (die Bitgrößen 0, 8, 16, 32 und 64 entsprechen int, int8, int16, int32 und int64).

Die aus der Datei gelesene Ganzzahl ist klein (dh sie sollte in ein normales int passen). Wenn ich jedoch eine Bitgröße von 0 übergebe, erhalte ich ein Ergebnis vom Typ int64(vermutlich, weil ich auf einem 64-Bit-Betriebssystem arbeite).

Warum passiert das? Wie bekomme ich nur einen normalen int? (Wenn jemand eine kurze Einführung hat, wann und warum ich die verschiedenen int-Typen verwenden sollte, wäre das großartig!)

Bearbeiten: Ich kann den int64 mit in einen normalen int konvertieren int([i64_var]). Aber ich verstehe immer noch nicht, warum ParseInt()ich einen int64 bekomme, wenn ich eine Bitgröße von 0 anfordere.

Isaac Dontje Lindell
quelle
2
Verwenden Sie Atoi der Kürze halber ? Gibt Ihre ParseInt-Funktion auch einen Fehler zurück?
Matt
2
Okay, jetzt bin ich etwas verwirrt. Wenn ich Atoi () benutze, gibt es mir ein int und alles funktioniert. Ich habe angerufen parseInt(s, 0, 0), was auf base10 schließen sollte (da die Zeichenfolge kein Basispräfix hat). Atoi ist jedoch eine Abkürzung für den Aufruf parseIntmit einer Basis von 10. Warum unterscheidet der Basisparameter den zurückgegebenen Typ?
Isaac Dontje Lindell
Der Basisparameter bestimmt, wie die Eingabezeichenfolge gelesen wird. Eine Zeichenfolge könnte wie "123" oder "0xBEEFCAKE" oder "1011101" oder "0677" aussehen. Alle haben eine andere Bedeutung und ergeben einen anderen numerischen Wert. Ein Basiswert von 0bedeutet, dass der Code versucht, dies selbst herauszufinden. Aber manchmal ist das nicht möglich. 11(dezimal) vs 11(binär) repräsentieren völlig unterschiedliche Werte.
Jimt
1
Okay, ich denke, was mich wirklich verwirrt, sind die Dokumente. Die Dokumente für Atoi sagen nur, dass es nur eine "Abkürzung für parseInt(s, 10, 0)" ist. Aber warum kehrt Atoi dann zurück, intwährend parseIntint64 zurückkehrt?
Isaac Dontje Lindell
1
Da ich nicht genau weiß warum, Atoiint atoi ( const char * str );
gehe

Antworten:

55
func ParseInt(s string, base int, bitSize int) (i int64, err error)

ParseInt kehrt immer zurück int64

bitSizedefiniert den Wertebereich. Wenn der Wert, der s entspricht, nicht durch eine vorzeichenbehaftete Ganzzahl der angegebenen Größe dargestellt werden kann, ist err.Err = ErrRange.

http://golang.org/pkg/strconv/#ParseInt

type int int

int ist ein vorzeichenbehafteter Integer-Typ mit einer Größe von mindestens 32 Bit. Es ist jedoch ein bestimmter Typ und kein Alias ​​für beispielsweise int32.

http://golang.org/pkg/builtin/#int

Könnte intalso in Zukunft größer als 32 Bit sein oder auf einigen Systemen wie intin C.

Ich denke, auf einigen Systemen ist es int64möglicherweise schneller als int32weil dieses System nur mit 64-Bit-Ganzzahlen funktioniert.

Hier ist ein Beispiel für einen Fehler, wenn bitSize8 ist

http://play.golang.org/p/_osjMqL6Nj

package main

import (
    "fmt"
    "strconv"
)

func main() {
    i, err := strconv.ParseInt("123456", 10, 8)
    fmt.Println(i, err)
}
Shuriken
quelle
22
In der Praxis wird Go normalerweise int64für inteine amd64-GOARCH und int32für eine int32-Bit-GOARCH verwendet. Zumindest mit dem Standard-Compiler bin ich mir bei gccgo nicht sicher. " intKönnte größer als 32 Bit sein ..." ist also nicht nur Spekulation, sondern eher wahrscheinlich, da die 64-Bit-Kompilierungsziele im Allgemeinen als Hauptzweig in Go angesehen werden.
LinearZoetrope
12
"In der Praxis verwendet Go normalerweise int64 für int auf einem amd64 [..]" - genauer gesagt, int entspricht immer der Prozessorbitgröße . Auf 64-Bit-Systemen ist es also 64-Bit, auf 32-Bit-Systemen 32-Bit. Ich denke gerne, dass es je nach Kompilierungsziel entweder ein Alias ​​von int32 oder int64 ist (auch wenn es nicht als Alias ​​implementiert ist, spielt es keine Rolle).
Zupa
@zupa Was ist die Quelle / Referenz für "int entspricht immer der Prozessorbitgröße"?
Kapad
29

Paket strconv

func ParseInt

func ParseInt(s string, base int, bitSize int) (i int64, err error)

ParseInt interpretiert einen String s in der angegebenen Basis (2 bis 36) und gibt den entsprechenden Wert i zurück. Wenn base == 0 ist, wird die Base durch das Präfix der Zeichenfolge impliziert: base 16 für "0x", base 8 für "0" und andernfalls base 10.

Das Argument bitSize gibt den Integer-Typ an, in den das Ergebnis passen muss. Die Bitgrößen 0, 8, 16, 32 und 64 entsprechen int, int8, int16, int32 und int64.

Die von ParseInt zurückgegebenen Fehler haben den konkreten Typ * NumError und enthalten err.Num = s. Wenn s leer ist oder ungültige Ziffern enthält, ist err.Err = ErrSyntax; Wenn der Wert, der s entspricht, nicht durch eine vorzeichenbehaftete Ganzzahl der angegebenen Größe dargestellt werden kann, ist err.Err = ErrRange.

ParseIntgibt immer einen int64Wert zurück. Je nach bitSizewird dieser Wert paßt in int, int8, int16, int32, oder int64. Wenn der Wert nicht durch eine vorzeichenbehaftete Ganzzahl der angegebenen Größe dargestellt werden kann bitSize, dann err.Err = ErrRange.

Die Go-Programmiersprachenspezifikation

Numerische Typen

Der Wert einer n-Bit-Ganzzahl ist n Bit breit und wird unter Verwendung der Zweierkomplementarithmetik dargestellt.

int8        the set of all signed  8-bit integers (-128 to 127)
int16       the set of all signed 16-bit integers (-32768 to 32767)
int32       the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64       the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)

Es gibt auch eine Reihe von vorab deklarierten numerischen Typen mit implementierungsspezifischen Größen:

uint     either 32 or 64 bits
int      same size as uint

intbeträgt je nach Implementierung entweder 32 oder 64 Bit. Normalerweise sind es 32 Bit für 32-Bit-Compiler und 64 Bit für 64-Bit-Compiler.

Um die Größe eines intoder herauszufinden uint, verwenden Sie strconv.IntSize.

Paket strconv

Konstanten

const IntSize = intSize

IntSizeist die Größe in Bits eines intoder uintWertes.

Zum Beispiel,

package main

import (
    "fmt"
    "runtime"
    "strconv"
)

func main() {
    fmt.Println(runtime.Compiler, runtime.GOARCH, runtime.GOOS)
    fmt.Println(strconv.IntSize)
}

Ausgabe:

gc amd64 linux
64
peterSO
quelle
7

strconv.ParseIntund Freunde geben 64-Bit-Versionen zurück, um die API sauber und einfach zu halten. Andernfalls müssten für jeden möglichen Rückgabetyp separate Versionen erstellt werden. Oder kehren Sie zurück interface{}, was dann eine Typzusicherung durchlaufen müsste. Nichts davon ist ideal.

int64wird gewählt, weil es eine beliebige Ganzzahlgröße bis einschließlich der unterstützten 64-Bit enthalten kann. Die Bitgröße, die Sie an die Funktion übergeben, stellt sicher, dass der Wert ordnungsgemäß auf den richtigen Bereich geklemmt wird. Sie können also einfach eine Typkonvertierung für den zurückgegebenen Wert durchführen, um ihn in einen beliebigen Ganzzahltyp umzuwandeln.

Der Unterschied zwischen intund int64ist architekturabhängig. intist einfach ein Alias ​​für eine 32-Bit- oder 64-Bit-Ganzzahl, abhängig von der Architektur, für die Sie kompilieren.

Für das anspruchsvolle Auge: Der zurückgegebene Wert ist eine vorzeichenbehaftete Ganzzahl. Es gibt eine separate strconv.ParseUintFunktion für vorzeichenlose Ganzzahlen, die uint64dieselbe Argumentation wie oben erläutert zurückgibt und folgt.

jimt
quelle
4
Nach dem, was ich bisher gesehen habe, ist dies fast richtig, außer dass ich nicht denke, dass intes einfach ein Alias ​​ist - es ist in der Tat ein bestimmter Typ. golang.org/pkg/builtin/#int
Isaac Dontje Lindell
Tatsächlich. Go macht kein Typ-Aliasing. So etwas type int int32ist als einzigartiger und separater Typ zu behandeln. Insbesondere, weil intdurch die Anwendung neuer Methoden neue Funktionen für den Typ definiert werden können.
Jimt
5

Für Ihre Zwecke strconv.Atoi()wäre das bequemer, denke ich.

Die anderen Antworten waren ziemlich ausführlich in intBezug auf die Erklärung des Typs, aber ich denke, ein Link zur Go-Sprachspezifikation ist hier verdient: http://golang.org/ref/spec#Numeric_types

Matt
quelle
0

In Go lang wird jeder Typ als separater Datentyp betrachtet, der nicht austauschbar mit dem Basistyp verwendet werden kann. Zum Beispiel,

type CustomInt64 int64

In der obigen Deklaration sind CustomInt64 und integriertes int64 zwei separate Datentypen und können nicht austauschbar verwendet werden.

Das Gleiche gilt für int, int32 und int64. All dies sind separate Datentypen, die nicht austauschbar verwendet werden können. Wenn int32 32 sein ganzzahliger Typ ist, ist int64 64 Bit und die Größe des generischen int-Typs ist plattformabhängig. Sie ist auf einem 32-Bit-System 32 Bit breit und auf einem 64-Bit-System 64 Bit breit. Wir müssen also vorsichtig und spezifisch sein, wenn wir generische Datentypen wie int, uint und float angeben. Es kann irgendwo im Code ein Problem verursachen und die Anwendung auf einer anderen Plattform zum Absturz bringen.

Umar Hayat
quelle