Eu tenho uma string contendo um inteiro (que foi lido de um arquivo).
Estou tentando converter string
para int
usando strconv.ParseInt()
. ParseInt
requer que eu forneça um tamanho de bits (tamanhos de bits 0, 8, 16, 32 e 64 correspondem a int, int8, int16, int32 e int64).
O inteiro lido do arquivo é pequeno (ou seja, deve caber em um int normal). Se eu passar um tamanho de bits de 0, porém, obtenho um resultado do tipo int64
(provavelmente porque estou executando em um sistema operacional de 64 bits).
Por que isso está acontecendo? Como faço para obter um int normal? (Se alguém tiver uma introdução rápida sobre quando e por que devo usar os diferentes tipos de int, seria incrível!)
Edit: posso converter o int64 em um int normal usando int([i64_var])
. Mas ainda não entendo por que ParseInt()
está me dando um int64 quando estou solicitando um tamanho de bits igual a 0.
parseInt(s, 0, 0)
, o que deve inferir base10 (já que a string não tem um prefixo de base). No entanto, Atoi é uma abreviação para chamarparseInt
com uma base de 10. Por que o parâmetro base faz diferença no tipo retornado?0
significa que o código tenta descobrir isso sozinho. Mas às vezes isso não é possível.11
(decimal) vs11
(binário) representam valores totalmente diferentes.parseInt(s, 10, 0)
". Mas por que então Atoi retornaint
enquantoparseInt
retorna int64?Atoi
foi adicionado simplesmente para acomodar as pessoas que estão mais familiarizadas com a API C:int atoi ( const char * str );
Respostas:
func ParseInt(s string, base int, bitSize int) (i int64, err error)
ParseInt sempre retorna
int64
bitSize
define faixa de valores. Se o valor correspondente a s não puder ser representado por um inteiro com sinal do tamanho fornecido, err.Err = ErrRange.http://golang.org/pkg/strconv/#ParseInt
type int int
int é um tipo inteiro assinado com pelo menos 32 bits de tamanho. É um tipo distinto, no entanto, e não um alias para, digamos, int32.
http://golang.org/pkg/builtin/#int
Portanto,
int
pode ser maior do que 32 bits no futuro ou em alguns sistemas como oint
C.Acho que em alguns sistemas
int64
pode ser mais rápido do queint32
porque esse sistema só funciona com inteiros de 64 bits.Aqui está um exemplo de erro quando
bitSize
é 8http://play.golang.org/p/_osjMqL6Nj
package main import ( "fmt" "strconv" ) func main() { i, err := strconv.ParseInt("123456", 10, 8) fmt.Println(i, err) }
fonte
int64
paraint
em um GOARCH amd64 eint32
paraint
em GOARCHes de 32 bits. Pelo menos com o compilador padrão, não tenho certeza sobre o gccgo. Portanto, "int
pode ser maior que 32 bits ..." não é apenas especulação, é na verdade bastante provável, já que os destinos de compilação de 64 bits são geralmente considerados o ramo principal do Go.ParseInt
sempre retorna umint64
valor. DependendobitSize
, este valor vai se encaixarint
,int8
,int16
,int32
, ouint64
. Se o valor não puder ser representado por um inteiro com sinal do tamanho fornecido porbitSize
, entãoerr.Err = ErrRange
.int
é de 32 ou 64 bits, dependendo da implementação. Normalmente é de 32 bits para compiladores de 32 bits e 64 bits para compiladores de 64 bits.Para descobrir o tamanho de um
int
ouuint
, usestrconv.IntSize
.Por exemplo,
package main import ( "fmt" "runtime" "strconv" ) func main() { fmt.Println(runtime.Compiler, runtime.GOARCH, runtime.GOOS) fmt.Println(strconv.IntSize) }
Resultado:
gc amd64 linux 64
fonte
strconv.ParseInt
e amigos retornam versões de 64 bits para manter a API limpa e simples. Caso contrário, seria necessário criar versões separadas para cada tipo de retorno possível. Ou returninterface{}
, que então teria que passar por uma declaração de tipo. Nenhum dos quais é ideal.int64
é escolhido porque pode conter qualquer tamanho de inteiro até, e incluindo, os 64 bits suportados. O tamanho do bit que você passa para a função garante que o valor seja fixado corretamente no intervalo correto. Portanto, você pode simplesmente fazer uma conversão de tipo no valor retornado, para transformá-lo em qualquer tipo de inteiro que você precisar.Quanto à diferença entre
int
eint64
, isso depende da arquitetura.int
é simplesmente um alias para um inteiro de 32 ou 64 bits, dependendo da arquitetura para a qual você está compilando.Para o olho mais perspicaz: O valor retornado é um número inteiro com sinal. Há uma
strconv.ParseUint
função separada para inteiros sem sinal, que retornauint64
e segue o mesmo raciocínio explicado acima.fonte
int
seja simplesmente um pseudônimo - é na verdade um tipo distinto. golang.org/pkg/builtin/#inttype int int32
deve ser tratado como um tipo único e separado. Notavelmente porque permite que novas funcionalidades sejam definidas para oint
tipo por meio da aplicação de novos métodos.Para seus propósitos,
strconv.Atoi()
seria mais conveniente, eu acho.As outras respostas foram bem exaustivas sobre a explicação do
int
tipo, mas acho que um link para a especificação da linguagem Go é merecido aqui: http://golang.org/ref/spec#Numeric_typesfonte
No Go lang, cada tipo é considerado um tipo de dados separado que não pode ser usado de forma intercambiável com o tipo base. Por exemplo,
type CustomInt64 int64
Na declaração acima, CustomInt64 e interno int64 são dois tipos de dados separados e não podem ser usados de forma intercambiável.
O mesmo é o caso com int, int32 e int64, todos esses são tipos de dados separados que não podem ser usados de forma intercambiável. Onde int32 é 32 seu tipo inteiro, int64 é 64 bits e o tamanho do tipo genérico int depende da plataforma. Tem 32 bits de largura em um sistema de 32 bits e 64 bits de largura em um sistema de 64 bits. Portanto, devemos ser cuidadosos e específicos ao especificar tipos de dados genéricos como int, uint e float. Isso pode causar um problema em algum lugar do código e travará o aplicativo em uma plataforma diferente.
fonte