Tengo una cadena que contiene un número entero (que se ha leído de un archivo).
Estoy tratando de convertir el string
a un int
using strconv.ParseInt()
. ParseInt
requiere que proporcione un tamaño de bits (los tamaños de bits 0, 8, 16, 32 y 64 corresponden a int, int8, int16, int32 e int64).
El entero leído del archivo es pequeño (es decir, debería caber en un int normal). Sin embargo, si paso un tamaño de bits de 0, obtengo un resultado de tipo int64
(presumiblemente porque estoy ejecutando un sistema operativo de 64 bits).
¿Por qué está pasando esto? ¿Cómo obtengo un int normal? (Si alguien tiene una introducción rápida sobre cuándo y por qué debería usar los diferentes tipos de int, ¡sería increíble!)
Editar: puedo convertir el int64 a un int normal usando int([i64_var])
. Pero todavía no entiendo por qué ParseInt()
me da un int64 cuando solicito un tamaño de bits de 0.
parseInt(s, 0, 0)
, lo que debería inferir base10 (ya que la cadena no tiene un prefijo base). Sin embargo, Atoi es una forma abreviada de llamarparseInt
con una base de 10. ¿Por qué el parámetro base hace una diferencia en el tipo devuelto?0
significa que el código intenta resolver esto por sí mismo. Pero a veces esto no es posible.11
(decimal) vs11
(binario) representan valores completamente diferentes.parseInt(s, 10, 0)
". Pero, ¿por qué entonces Atoi regresaint
mientrasparseInt
regresa int64?Atoi
se agregó simplemente para adaptarse a las personas que están más familiarizadas con la API de C:int atoi ( const char * str );
Respuestas:
func ParseInt(s string, base int, bitSize int) (i int64, err error)
ParseInt siempre regresa
int64
bitSize
define rango de valores. Si el valor correspondiente as no puede ser representado por un entero con signo del tamaño dado, err.Err = ErrRange.http://golang.org/pkg/strconv/#ParseInt
type int int
int es un tipo entero con signo que tiene al menos 32 bits de tamaño. Sin embargo, es un tipo distinto y no un alias para, digamos, int32.
http://golang.org/pkg/builtin/#int
Por
int
lo tanto, podría ser mayor que 32 bits en el futuro o en algunos sistemas comoint
C.Supongo que en algunos sistemas
int64
puede ser más rápidoint32
porque ese sistema solo funciona con enteros de 64 bits.Aquí hay un ejemplo de error cuando
bitSize
es 8http://play.golang.org/p/_osjMqL6Nj
package main import ( "fmt" "strconv" ) func main() { i, err := strconv.ParseInt("123456", 10, 8) fmt.Println(i, err) }
fuente
int64
forint
en un GOARCH amd64 yint32
paraint
en GOARCH de 32 bits. Al menos con el compilador predeterminado, no estoy seguro de gccgo. Entonces, "int
podría ser mayor que 32 bits ..." no es solo una especulación, en realidad es bastante probable ya que los objetivos de compilación de 64 bits generalmente se consideran la rama principal en Go.ParseInt
siempre devuelve unint64
valor. En función debitSize
este valor se ajusta aint
,int8
,int16
,int32
, oint64
. Si el valor no puede ser representado por un entero con signo del tamaño dado porbitSize
, entonceserr.Err = ErrRange
.int
es de 32 o 64 bits, según la implementación. Por lo general, es de 32 bits para compiladores de 32 bits y de 64 bits para compiladores de 64 bits.Para averiguar el tamaño de un
int
ouint
, utilicestrconv.IntSize
.Por ejemplo,
package main import ( "fmt" "runtime" "strconv" ) func main() { fmt.Println(runtime.Compiler, runtime.GOARCH, runtime.GOOS) fmt.Println(strconv.IntSize) }
Salida:
gc amd64 linux 64
fuente
strconv.ParseInt
y sus amigos regresan versiones de 64 bits para mantener la API limpia y simple. De lo contrario, habría que crear versiones independientes para cada posible tipo de devolución. O returninterface{}
, que luego tendría que pasar por una aserción de tipo. Ninguno de los cuales es ideal.int64
se elige porque puede contener cualquier tamaño de entero hasta, inclusive, los 64 bits admitidos. El tamaño de bit que pasa a la función garantiza que el valor se fije correctamente en el rango correcto. Entonces, simplemente puede hacer una conversión de tipo en el valor devuelto, para convertirlo en cualquier tipo de entero que necesite.En cuanto a la diferencia entre
int
yint64
, esto depende de la arquitectura.int
es simplemente un alias para un entero de 32 bits o de 64 bits, según la arquitectura para la que está compilando.Para el ojo perspicaz: el valor devuelto es un entero con signo. Hay una
strconv.ParseUint
función separada para enteros sin signo, que devuelveuint64
y sigue el mismo razonamiento que se explicó anteriormente.fuente
int
sea simplemente un alias, de hecho es un tipo distinto. golang.org/pkg/builtin/#inttype int int32
debe tratarse como un tipo único y separado. Sobre todo porque permite definir nuevas funcionalidades para elint
tipo mediante la aplicación de nuevos métodos.Para sus propósitos,
strconv.Atoi()
creo que sería más conveniente.Las otras respuestas han sido bastante exhaustivas sobre la explicación del
int
tipo, pero creo que se merece un enlace a la especificación del idioma Go aquí: http://golang.org/ref/spec#Numeric_typesfuente
En Go lang, cada tipo se considera un tipo de datos independiente que no se puede utilizar indistintamente con el tipo base. Por ejemplo,
type CustomInt64 int64
En la declaración anterior, CustomInt64 e int64 integrado son dos tipos de datos separados y no se pueden usar indistintamente.
Lo mismo ocurre con int, int32 e int64, todos estos son tipos de datos separados que no se pueden usar indistintamente. Donde int32 es 32 su tipo entero, int64 es 64 bits y el tamaño del tipo int genérico depende de la plataforma. Tiene 32 bits de ancho en un sistema de 32 bits y 64 bits de ancho en un sistema de 64 bits. Por lo tanto, debemos ser cuidadosos y específicos al especificar tipos de datos genéricos como int, uint y float. Puede causar un problema en algún lugar del código y bloquear la aplicación en una plataforma diferente.
fuente