Qual è la differenza tra int e int64 in Go?


86

Ho una stringa contenente un numero intero (che è stato letto da un file).

Sto cercando di convertire il file stringin un file intusing strconv.ParseInt(). ParseIntrichiede che io fornisca una dimensione in bit (le dimensioni in bit 0, 8, 16, 32 e 64 corrispondono a int, int8, int16, int32 e int64).

L'intero letto dal file è piccolo (cioè dovrebbe rientrare in un normale int). Se passo un bit di 0, tuttavia, ottengo un risultato di tipo int64(presumibilmente perché sto eseguendo un sistema operativo a 64 bit).

Perché sta succedendo? Come ottengo appena un int normale? (Se qualcuno ha un rapido manuale su quando e perché dovrei usare i diversi tipi di int, sarebbe fantastico!)

Modifica: posso convertire int64 in un normale int usando int([i64_var]). Ma ancora non capisco perché ParseInt()mi dia un int64 quando richiedo un bit di 0.


2
Usa Atoi per brevità? Inoltre, la tua funzione ParseInt restituisce un errore?
Matt

2
Ok, ora sono un po 'confuso. Se uso Atoi (), mi dà un int e tutto funziona. Stavo chiamando parseInt(s, 0, 0), che dovrebbe dedurre base10 (poiché la stringa non ha un prefisso di base). Tuttavia, Atoi è un'abbreviazione per chiamare parseIntcon una base di 10. Perché il parametro di base fa la differenza nel tipo restituito?
Isaac Dontje Lindell

Il parametro di base determina la modalità di lettura della stringa di input. Una stringa potrebbe essere "123" o "0xBEEFCAKE" o "1011101" o "0677". Tutti hanno un significato diverso e producono un valore numerico diverso. Un valore base di 0significa che il codice cerca di capirlo da solo. Ma a volte questo non è possibile. 11(decimale) vs 11(binario) rappresentano valori completamente diversi.
jimt

1
Ok, immagino che quello su cui sono davvero confuso siano i documenti. I documenti di Atoi dicono solo che è solo una "scorciatoia per parseInt(s, 10, 0)". Ma perché allora Atoi ritorna intmentre parseIntritorna int64?
Isaac Dontje Lindell

1
Non sapendo esattamente perché, presumo che sia Atoistato aggiunto semplicemente per accogliere le persone che hanno più familiarità con l'API C:int atoi ( const char * str );
jimt

Risposte:


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

ParseInt ritorna sempre int64

bitSizedefinisce l'intervallo di valori. Se il valore corrispondente a s non può essere rappresentato da un intero con segno della dimensione data, err.Err = ErrRange.

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

type int int

int è un tipo intero con segno che ha una dimensione di almeno 32 bit. È un tipo distinto, tuttavia, e non un alias, ad esempio, int32.

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

Quindi intpotrebbe essere più grande di 32 bit in futuro o su alcuni sistemi come intin C.

Immagino che su alcuni sistemi int64potrebbe essere più veloce di int32perché quel sistema funziona solo con numeri interi a 64 bit.

Ecco un esempio di errore quando bitSizeè 8

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

package main

import (
    "fmt"
    "strconv"
)

func main() {
    i, err := strconv.ParseInt("123456", 10, 8)
    fmt.Println(i, err)
}

22
In pratica, Go di solito usa int64per intsu GOARCH amd64 e int32per GOARCH inta 32 bit. Almeno con il compilatore predefinito, non sono sicuro di gccgo. Quindi " intpotrebbe essere più grande di 32 bit ..." non è solo una speculazione, in realtà è piuttosto probabile poiché gli obiettivi di compilazione a 64 bit sono generalmente considerati il ​​ramo principale in Go.
LinearZoetrope

12
"In pratica, Go di solito usa int64 per int su un amd64 [..]" - più precisamente, int è sempre uguale alla dimensione in bit del processore . Quindi su sistemi a 64 bit, è a 64 bit, su sistemi a 32 bit, è a 32 bit. Mi piace pensare che sia un alias di int32 o int64 a seconda della destinazione della compilazione (anche se non è implementato come alias, non importa).
zupa

@zupa qual è la sorgente / riferimento per "int è sempre uguale alla dimensione in bit del processore"?
kapad

29

Pacchetto strconv

func ParseInt

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

ParseInt interpreta una stringa s nella base data (da 2 a 36) e restituisce il valore corrispondente i. Se base == 0, la base è implicita nel prefisso della stringa: base 16 per "0x", base 8 per "0" e base 10 altrimenti.

L'argomento bitSize specifica il tipo intero in cui deve rientrare il risultato. Le dimensioni dei bit 0, 8, 16, 32 e 64 corrispondono a int, int8, int16, int32 e int64.

Gli errori restituiti da ParseInt hanno un tipo concreto * NumError e includono err.Num = s. Se s è vuoto o contiene cifre non valide, err.Err = ErrSyntax; se il valore corrispondente a s non può essere rappresentato da un intero con segno della dimensione data, err.Err = ErrRange.

ParseIntrestituisce sempre un int64valore. A seconda bitSize, questo valore si inserisce in int, int8, int16, int32, o int64. Se il valore non può essere rappresentato da un numero intero con segno della dimensione data da bitSize, allora err.Err = ErrRange.

La specifica del linguaggio di programmazione Go

Tipi numerici

Il valore di un intero a n bit è largo n bit e rappresentato utilizzando l'aritmetica del complemento a due.

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)

Esiste anche un set di tipi numerici predichiarati con dimensioni specifiche dell'implementazione:

uint     either 32 or 64 bits
int      same size as uint

intè di 32 o 64 bit, a seconda dell'implementazione. Di solito sono 32 bit per i compilatori a 32 bit e 64 bit per i compilatori a 64 bit.

Per scoprire la dimensione di un intor uint, usa strconv.IntSize.

Pacchetto strconv

Costanti

const IntSize = intSize

IntSizeè la dimensione in bit di un valore into uint.

Per esempio,

package main

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

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

Produzione:

gc amd64 linux
64

7

strconv.ParseInte amici restituiscono le versioni a 64 bit per mantenere l'API pulita e semplice. Altrimenti si dovrebbero creare versioni separate per ogni possibile tipo restituito. O return interface{}, che dovrebbe quindi passare attraverso un'asserzione di tipo. Nessuno dei quali è l'ideale.

int64è scelto, perché può contenere qualsiasi dimensione intera fino a, e inclusi, i 64 bit supportati. La dimensione dei bit che si passa alla funzione garantisce che il valore sia correttamente bloccato nell'intervallo corretto. Quindi puoi semplicemente fare una conversione di tipo sul valore restituito, per trasformarlo in qualsiasi tipo di numero intero richiesto.

Per quanto riguarda la differenza tra inte int64, questa dipende dall'architettura.intè semplicemente un alias per un numero intero a 32 o 64 bit, a seconda dell'architettura per la quale stai compilando.

Per gli occhi più esigenti: il valore restituito è un numero intero con segno. Esiste una strconv.ParseUintfunzione separata per gli interi senza segno, che restituisce uint64e segue lo stesso ragionamento spiegato sopra.


4
Da quello che ho visto finora, questo è quasi corretto, tranne per il fatto che non penso intsia semplicemente un alias - in realtà è un tipo distinto. golang.org/pkg/builtin/#int
Isaac Dontje Lindell

Infatti. Go non esegue realmente l'alias di tipo. Qualcosa di simile type int int32deve essere trattato come un tipo unico e separato. In particolare perché consente di definire nuove funzionalità per il inttipo attraverso l'applicazione di nuovi metodi.
jimt


0

In Go lang, ogni tipo è considerato come un tipo di dati separato che non può essere utilizzato in modo intercambiabile con il tipo di base. Per esempio,

type CustomInt64 int64

Nella dichiarazione precedente, CustomInt64 e int64 integrato sono due tipi di dati separati e non possono essere utilizzati in modo intercambiabile.

Lo stesso è il caso di int, int32 e int64, tutti questi sono tipi di dati separati che non possono essere utilizzati in modo intercambiabile. Dove int32 è 32 il suo tipo intero, int64 è 64 bit e la dimensione del tipo int generico dipende dalla piattaforma. È largo 32 bit su un sistema a 32 bit e 64 bit su un sistema a 64 bit. Quindi dobbiamo essere attenti e specifici mentre specifichiamo tipi di dati generici come int, uint e float. Potrebbe causare un problema da qualche parte nel codice e arrestare l'applicazione su una piattaforma diversa.

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.