Sự khác biệt giữa int và int64 trong Go là gì?


86

Tôi có một chuỗi chứa một số nguyên (đã được đọc từ một tệp).

Tôi đang cố gắng để chuyển đổi stringmột intsử dụng strconv.ParseInt(). ParseIntyêu cầu tôi cung cấp kích thước bit (kích thước bit 0, 8, 16, 32 và 64 tương ứng với int, int8, int16, int32 và int64).

Số nguyên được đọc từ tệp là nhỏ (tức là nó phải vừa với một số nguyên thông thường). Tuy nhiên, nếu tôi chuyển kích thước bit là 0, tôi nhận được kết quả là loại int64(có lẽ vì tôi đang chạy trên hệ điều hành 64 bit).

Tại sao chuyện này đang xảy ra? Làm cách nào để tôi có được một số nguyên bình thường? (Nếu ai đó biết nhanh về thời điểm và lý do tôi nên sử dụng các kiểu int khác nhau, điều đó thật tuyệt vời!)

Chỉnh sửa: Tôi có thể chuyển đổi int64 thành int bình thường bằng cách sử dụng int([i64_var]). Nhưng tôi vẫn không hiểu tại sao ParseInt()lại cấp cho tôi một int64 khi tôi yêu cầu kích thước bit là 0.


2
Sử dụng Atoi cho ngắn gọn? Ngoài ra, hàm ParseInt của bạn có trả lại lỗi không?
Matt

2
Được rồi, bây giờ tôi hơi bối rối. Nếu tôi sử dụng Atoi (), nó cho tôi một int và mọi thứ đều hoạt động. Tôi đang gọi parseInt(s, 0, 0), điều này sẽ suy ra base10 (vì chuỗi không có tiền tố cơ sở). Tuy nhiên, Atoi là viết tắt để gọi parseIntw / a cơ sở là 10. Tại sao tham số cơ sở tạo ra sự khác biệt trong kiểu trả về?
Isaac Dontje Lindell,

Tham số cơ sở xác định cách đọc chuỗi đầu vào. Một chuỗi có thể trông giống như "123" hoặc "0xBEEFCAKE" hoặc "1011101" hoặc "0677". Tất cả đều có ý nghĩa khác nhau và mang lại giá trị số khác nhau. Giá trị cơ sở của 0nghĩa là mã cố gắng tự tìm ra điều này. Nhưng đôi khi điều này là không thể. 11(thập phân) và 11(nhị phân) đại diện cho các giá trị hoàn toàn khác nhau.
jimt

1
Được rồi, tôi đoán điều tôi thực sự bối rối là tài liệu. Các tài liệu dành cho Atoi chỉ nói rằng nó chỉ là "viết tắt của parseInt(s, 10, 0)". Nhưng tại sao sau đó Atoi trả về inttrong khi trả về int64 parseInt?
Isaac Dontje Lindell,

1
Không biết chính xác lý do tại sao, tôi sẽ cho rằng Atoiđã được bổ sung đơn giản để phù hợp với những người đã quen thuộc hơn với C API:int atoi ( const char * str );
jimt

Câu trả lời:


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

ParseInt luôn trả về int64

bitSizexác định phạm vi giá trị. Nếu giá trị tương ứng với s không thể được biểu diễn bằng một số nguyên có dấu có kích thước đã cho, thì err.Err = ErrRange.

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

type int int

int là kiểu số nguyên có dấu có kích thước ít nhất 32 bit. Tuy nhiên, nó là một kiểu riêng biệt và không phải là bí danh cho int32.

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

Vì vậy, intcó thể lớn hơn 32 bit trong tương lai hoặc trên một số hệ thống như inttrong C.

Tôi đoán trên một số hệ thống int64có thể nhanh hơn int32vì hệ thống đó chỉ hoạt động với số nguyên 64 bit.

Đây là ví dụ về lỗi khi bitSizelà 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
Trong thực tế, Go thường sử dụng int64cho intGOARCH amd64 và int32cho GOARCH int32 bit. Ít nhất là với trình biên dịch mặc định, tôi không chắc về gccgo. Vì vậy, " intcó thể lớn hơn 32 bit ..." không chỉ là suy đoán, nó thực sự có khả năng xảy ra vì các mục tiêu biên dịch 64 bit thường được coi là nhánh chính trong cờ vây.
LinearZoetrope

12
"Trong thực tế, Go thường sử dụng int64 cho int trên amd64 [..]" - chính xác hơn, int luôn bằng kích thước bit của bộ xử lý . Vì vậy, trên hệ thống 64 bit, nó là 64 bit, trên hệ thống 32 bit, nó là 32 bit. Tôi thích nghĩ đó là bí danh của int32 hoặc int64 tùy thuộc vào mục tiêu biên dịch của bạn (ngay cả khi nó không được triển khai dưới dạng bí danh, cũng không quan trọng).
zupa

@zupa nguồn / tham chiếu cho "int luôn bằng kích thước bit của bộ xử lý" là gì?
kapad

29

Gói strconv

func ParseInt

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

ParseInt diễn giải một chuỗi s trong cơ sở đã cho (2 đến 36) và trả về giá trị i tương ứng. Nếu cơ số == 0, cơ số được ngụ ý bởi tiền tố của chuỗi: cơ số 16 cho "0x", cơ sở 8 cho "0" và cơ sở 10 nếu không.

Đối số bitSize chỉ định kiểu số nguyên mà kết quả phải khớp vào. Kích thước bit 0, 8, 16, 32 và 64 tương ứng với int, int8, int16, int32 và int64.

Các lỗi mà ParseInt trả về có kiểu cụ thể là * NumError và bao gồm cả lỗi. Num = s. Nếu s trống hoặc chứa các chữ số không hợp lệ, err.Err = ErrSyntax; nếu giá trị tương ứng với s không thể được biểu diễn bằng số nguyên có dấu có kích thước đã cho, thì err.Err = ErrRange.

ParseIntluôn trả về một int64giá trị. Tùy thuộc vào bitSize, giá trị này sẽ phù hợp với int, int8, int16, int32, hoặc int64. Nếu giá trị không thể được biểu diễn bằng một số nguyên có dấu có kích thước được cho bởi bitSizethì err.Err = ErrRange.

Đặc tả ngôn ngữ lập trình Go

Loại số

Giá trị của một số nguyên n bit rộng n bit và được biểu diễn bằng số học phần bù của hai.

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)

Ngoài ra còn có một tập hợp các kiểu số được khai báo trước với các kích thước dành riêng cho việc triển khai:

uint     either 32 or 64 bits
int      same size as uint

intlà 32 hoặc 64 bit, tùy thuộc vào việc triển khai. Thông thường nó là 32 bit cho trình biên dịch 32 bit và 64 bit cho trình biên dịch 64 bit.

Để tìm ra kích thước của một inthoặc uint, hãy sử dụng strconv.IntSize.

Gói strconv

Hằng số

const IntSize = intSize

IntSizelà kích thước tính bằng bit của một inthoặc uintgiá trị.

Ví dụ,

package main

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

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

Đầu ra:

gc amd64 linux
64

7

strconv.ParseIntvà bạn bè trả lại phiên bản 64-bit để giữ cho API sạch sẽ và đơn giản. Nếu không, người ta sẽ phải tạo các phiên bản riêng biệt cho từng loại trả lại có thể có. Hoặc quay lại interface{}, sau đó sẽ phải trải qua một xác nhận kiểu. Không có cái nào là lý tưởng.

int64được chọn, vì nó có thể chứa bất kỳ kích thước số nguyên nào lên đến và bao gồm cả 64-bit được hỗ trợ. Kích thước bit bạn truyền vào hàm, đảm bảo rằng giá trị được kẹp đúng vào phạm vi chính xác. Vì vậy, bạn có thể chỉ cần thực hiện chuyển đổi kiểu trên giá trị trả về, để biến nó thành bất kỳ kiểu số nguyên nào bạn yêu cầu.

Đối với sự khác biệt giữa intint64, điều này phụ thuộc vào kiến ​​trúc. intchỉ đơn giản là bí danh cho số nguyên 32 bit hoặc 64 bit, tùy thuộc vào kiến ​​trúc mà bạn đang biên dịch.

Đối với con mắt sáng suốt: Giá trị trả về là một số nguyên có dấu. Có một strconv.ParseUinthàm riêng cho số nguyên không dấu, trả về uint64và tuân theo lý luận tương tự như đã giải thích ở trên.


4
Từ những gì tôi đã thấy cho đến nay, điều này gần như chính xác, ngoại trừ việc tôi không nghĩ intchỉ đơn giản là một bí danh - nó thực tế là một kiểu riêng biệt. golang.org/pkg/builtin/#int
Isaac Dontje Lindell

Thật. Go không thực sự gõ răng cưa. Một cái gì đó giống như type int int32được coi là một loại duy nhất và riêng biệt. Đáng chú ý bởi vì nó cho phép xác định chức năng mới cho intkiểu thông qua việc áp dụng các phương pháp mới.
jimt

5

Đối với mục đích của bạn, strconv.Atoi()tôi nghĩ sẽ thuận tiện hơn.

Các câu trả lời khác đã khá đầy đủ về việc giải thích intloại, nhưng tôi nghĩ rằng một liên kết đến đặc tả ngôn ngữ Go có sẵn ở đây: http://golang.org/ref/spec#Numeric_types


0

Trong Go lang, mỗi kiểu được coi là kiểu dữ liệu riêng biệt không thể được sử dụng thay thế cho kiểu cơ sở. Ví dụ,

type CustomInt64 int64

Trong phần khai báo trên, CustomInt64 và int64 tích hợp là hai kiểu dữ liệu riêng biệt và không thể được sử dụng thay thế cho nhau.

Trường hợp của int, int32 và int64 cũng vậy, tất cả đều là những kiểu dữ liệu riêng biệt không thể sử dụng thay thế cho nhau. Trong đó int32 là 32 kiểu số nguyên của nó, int64 là 64 bit và kích thước của kiểu int chung phụ thuộc vào nền tảng. Nó rộng 32 bit trên hệ thống 32 bit và rộng 64 bit trên hệ thống 64 bit. Vì vậy, chúng ta phải cẩn thận và cụ thể trong khi chỉ định các kiểu dữ liệu chung chung như int, uint và float. Nó có thể gây ra sự cố ở đâu đó trong mã và sẽ làm sập ứng dụng trên một nền tảng khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.