У чому різниця між int та int64 у Go?


86

У мене є рядок, що містить ціле число (яке було прочитано з файлу).

Я намагаюся перетворити stringв intвикористання strconv.ParseInt(). ParseIntвимагає, щоб я надавав бітовий розмір (бітові розміри 0, 8, 16, 32 та 64 відповідають int, int8, int16, int32 та int64).

Ціле число, прочитане з файлу, невелике (тобто воно повинно вміщуватися в звичайному int). Якщо я передаю бітовий розмір 0, однак, я отримую результат типу int64(мабуть, тому, що я працюю на 64-розрядної ОС).

Чому це відбувається? Як я можу отримати звичайний int? (Якщо хтось швидко описує, коли і чому я повинен використовувати різні типи int, це було б здорово!)

Редагувати: я можу перетворити int64 на звичайний int, використовуючи int([i64_var]). Але я все ще не розумію, чому ParseInt()мені дають int64, коли я вимагаю розмір 0.


2
Використовуйте Atoi для стислості? Також ваша функція ParseInt повертає помилку?
Метт

2
Гаразд, зараз я трохи розгублений. Якщо я використовую Atoi (), це дає мені int, і все працює. Я дзвонив parseInt(s, 0, 0), який повинен зробити висновок base10 (оскільки рядок не має базового префікса). Однак Atoi - це скорочення для виклику parseIntбез бази 10. Чому базовий параметр впливає на тип, що повертається?
Isaac Dontje Lindell

Базовий параметр визначає спосіб читання вхідного рядка. Рядок може виглядати як "123", "0xBEEFCAKE", "1011101" або "0677". Усі вони мають різне значення і дають різне числове значення. Базове значення 0означає, що код намагається зрозуміти це самостійно. Але іноді це неможливо. 11(десяткові) проти 11(двійкові) представляють абсолютно різні значення.
Jimt

1
Гаразд, я здогадуюсь, що мене справді бентежить - це документи. У документації до Atoi сказано лише, що це просто "скорочення parseInt(s, 10, 0)". Але чому тоді Atoi повертається, intколи parseIntповертає int64?
Isaac Dontje Lindell

1
Не знаючи точно, чому, я припущу, що це Atoiбуло додано просто для розміщення людей, які більше знайомі з C API:int atoi ( const char * str );
jimt

Відповіді:


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

ParseInt завжди повертається int64

bitSizeвизначає діапазон значень. Якщо значення, яке відповідає s, не може бути представлене цілим числом із зазначеним розміром, err.Err = ErrRange.

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

type int int

int - це цілий тип із підписом, розмір якого не менше 32 біт. Однак це виразний тип, а не псевдонім, скажімо, int32.

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

Тож intможе бути більше 32 біт у майбутньому або на деяких системах, таких як intC.

Я думаю, на деяких системах це int64може бути швидше, ніж int32тому, що ця система працює лише з 64-бітними цілими числами.

Ось приклад помилки, коли 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
На практиці, як правило , Go використовується int64для intна amd64 GOARCH і int32для int32-бітових GOARCHes. Принаймні з типовим компілятором, я не впевнений у gccgo. Отже, " intможе бути більше 32 біт ..." - це не просто спекуляція, це насправді досить ймовірно, оскільки цілі 64-бітної компіляції зазвичай вважаються головною гілкою в Go.
LinearZoetrope

12
"На практиці Go зазвичай використовує int64 для int на amd64 [..]" - точніше, int завжди дорівнює бітовому розміру процесора . Отже, на 64-бітних системах це 64-бітна система, на 32-бітних системах це 32-бітна. Мені подобається думати, що це або псевдонім int32, або int64 залежно від вашої цілі компіляції (навіть якщо він не реалізований як псевдонім, не має значення).
зупа

@zupa яке джерело / посилання для "int завжди дорівнює бітовому розміру процесора"?
kapad

29

Пакет strconv

func ParseInt

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

ParseInt інтерпретує рядок s у заданій основі (від 2 до 36) і повертає відповідне значення i. Якщо base == 0, під базою мається на увазі префікс рядка: base 16 для "0x", base 8 для "0", і base 10 в іншому випадку.

Аргумент bitSize визначає цілочисельний тип, до якого повинен вписуватися результат. Розміри бітів 0, 8, 16, 32 та 64 відповідають int, int8, int16, int32 та int64.

Помилки, які повертає ParseInt, мають конкретний тип * NumError і включають err.Num = s. Якщо s порожнє або містить недійсні цифри, err.Err = ErrSyntax; якщо значення, що відповідає s, не може бути представлене цілим числом із зазначеним розміром, err.Err = ErrRange.

ParseIntзавжди повертає int64значення. В залежності від того bitSize, це значення буде вписуватися в int, int8, int16, int32, або int64. Якщо значення не може бути представлене підписаним цілим числом розміру, заданого bitSize, тоді err.Err = ErrRange.

Специфікація мови програмування Go

Числові типи

Значення n-бітового цілого числа має ширину в n бітів і представляється за допомогою арифметики доповнення двох.

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)

Існує також набір заздалегідь оголошених числових типів із конкретними розмірами:

uint     either 32 or 64 bits
int      same size as uint

intдорівнює 32 або 64 біта, залежно від реалізації. Зазвичай це 32 біти для 32-розрядних компіляторів і 64 біти для 64-розрядних компіляторів.

Щоб дізнатись розмір intабо uint, скористайтесь strconv.IntSize.

Пакет strconv

Константи

const IntSize = intSize

IntSize- це розмір у бітах значення intабо uint.

Наприклад,

package main

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

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

Вихід:

gc amd64 linux
64

7

strconv.ParseIntі друзі повертають 64-розрядні версії, щоб підтримувати API чистим і простим. В іншому випадку потрібно було б створити окремі версії для кожного можливого типу повернення. Або повернення interface{}, яке потім мало б пройти через твердження типу. Жоден з яких не є ідеальним.

int64вибрано, оскільки він може містити будь-який цілий розмір до, включаючи, підтримувані 64-біти. Бітовий розмір, який ви передаєте у функцію, гарантує, що значення правильно зафіксовано в правильному діапазоні. Тож ви можете просто перетворити тип на повернене значення, щоб перетворити його на будь-який цілочисельний тип, який вам потрібен.

Що стосується різниці між intі int64, то це залежить від архітектури. int- це просто псевдонім для 32-розрядного або 64-розрядного цілого числа, залежно від архітектури, для якої ви компілюєте.

Для проникливого ока: Повернене значення - це підписане ціле число. Існує окрема strconv.ParseUintфункція для цілих чисел без знака, яка повертається uint64і виконує ті самі міркування, що описані вище.


4
З того, що я бачив на сьогоднішній день, це майже правильно, за винятком того, що я не думаю, що intце просто псевдонім - це насправді чіткий тип. golang.org/pkg/builtin/#int
Isaac Dontje Lindell

Справді. Go насправді не робить псевдонімів. Щось схоже на те type int int32, щоб трактувати як унікальний і окремий тип. Зокрема тому, що це дозволяє визначити нову функціональність для intтипу за допомогою застосування нових методів.
Jimt


0

У Go lang кожен тип розглядається як окремий тип даних, який не можна використовувати як взаємозамінний з базовим типом. Наприклад,

type CustomInt64 int64

У наведеній вище декларації CustomInt64 та вбудований int64 є двома окремими типами даних і не можуть використовуватися як взаємозамінні.

Те саме відбувається з int, int32 та int64, все це окремі типи даних, які не можна використовувати як взаємозамінні. Якщо int32 дорівнює 32, це цілий тип, int64 дорівнює 64 бітам, а розмір загального типу int залежить від платформи. Він має 32-бітну ширину для 32-бітної системи та 64-бітну ширину для 64-бітної системи. Тож ми повинні бути обережними та конкретними, визначаючи загальні типи даних, такі як int, uint та float. Це може спричинити проблему десь у коді та призведе до збою програми на іншій платформі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.