Menu

Kiểu dữ liệu Golang: int, float64, string, bool, byte, rune

Các kiểu có sẵn của Go: kích thước và phạm vi số nguyên, float32 và float64, bool, string, byte và rune, số phức, giá trị zero, và cách in kiểu của một giá trị bằng %T.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

Các kiểu cơ bản của Go là số, boolean và chuỗi. Mỗi biến có đúng một kiểu dữ liệu (data type), cố định lúc biên dịch, và Go không bao giờ tự chuyển đổi giữa các kiểu cho bạn. %T in ra kiểu của bất kỳ giá trị nào:

Để ý 'G' được in ra là 71 với kiểu int32: một ký tự trong dấu nháy đơn là một rune, tức là một con số (code point Unicode). rune là bí danh của int32 (cùng một kiểu với tên thứ hai), nên %T báo int32. Tương tự, byte báo uint8.

Số nguyên

KiểuKích thướcPhạm vi
int88 bit-128 đến 127
int1616 bit-32.768 đến 32.767
int3232 bitkhoảng -2,1 tỷ đến 2,1 tỷ
int6464 bitkhoảng -9,2 tỷ tỷ đến 9,2 tỷ tỷ
uint8 (byte)8 bit0 đến 255
uint1616 bit0 đến 65.535
uint3232 bit0 đến khoảng 4,3 tỷ
uint6464 bit0 đến khoảng 18,4 tỷ tỷ
int, uint32 hoặc 64 bitkích thước word của nền tảng
uintptrkích thước của nền tảngchứa giá trị con trỏ, cho code cấp thấp

Mặc định hãy dùng int. len() trả về int, chỉ số slice là int, và bộ đếm vòng lặp là int. Trên mọi nền tảng 64 bit, int là 64 bit. Chỉ dùng các kiểu có kích thước cố định khi kích thước là một phần của giao ước: int32 trong định dạng tệp nhị phân, uint8 cho byte thô, int64 cho Unix timestamp tính bằng nano giây.

Tránh dùng kiểu không dấu cho các đại lượng "không thể âm", như số đếm. Trừ quá số 0 sẽ quay vòng thành một số rất lớn thay vì tạo ra một số âm mà bạn bắt được.

Giới hạn và tràn số

Package math có một hằng số cho mỗi giới hạn. Lúc chạy, phép tính số nguyên bị tràn sẽ âm thầm quay vòng:

Không panic, không lỗi: 127 + 1 thành -128. Chỉ các biểu thức hằng được kiểm tra lúc biên dịch (var b int8 = 128 không biên dịch được). Nếu dữ liệu của bạn có thể bị tràn, hãy kiểm tra trước phép tính hoặc dùng math/big.

Literal số nguyên

million := 1_000_000   // underscores for readability (Go 1.13+)
mask := 0xFF           // hexadecimal
perm := 0o755          // octal (also the older form 0755)
flags := 0b1010        // binary

Số thực

KiểuKích thướcĐộ chính xác
float3232 bitkhoảng 6 đến 9 chữ số có nghĩa
float6464 bitkhoảng 15 đến 17 chữ số có nghĩa

Một literal có dấu thập phân hoặc số mũ (2.5, 1e6) mặc định là float64, và package math nhận và trả về float64. Hãy dùng nó, trừ khi bộ nhớ của một mảng lớn là vấn đề.

Số thực được lưu ở dạng nhị phân, nên phần lớn phân số thập phân chỉ là giá trị xấp xỉ:

Từ đó có hai quy tắc. Không bao giờ so sánh số thực bằng == sau khi tính toán. Và không bao giờ lưu tiền bằng số thực: hãy dùng số nguyên tính theo xu, hoặc một thư viện số thập phân.

Chia một số thực cho 0 cho ra +Inf, -Inf hoặc NaN thay vì gây panic. Chia một số nguyên cho 0 gây panic lúc chạy (runtime error: integer divide by zero), và số chia là hằng số 0 thì là lỗi biên dịch.

Boolean

bool chứa true hoặc false, và giá trị zero của nó là false. Go không coi số, chuỗi rỗng hay nil là boolean. if count {} là lỗi biên dịch; hãy viết if count > 0 {}. Các toán tử là &&, || và !, và && với || có tính đoản mạch.

Chuỗi

Một string là một dãy byte bất biến, thường là văn bản UTF-8. len(s) đếm byte, không phải ký tự:

é chiếm hai byte trong UTF-8, nên len báo 6 cho năm ký tự. Chuỗi trong dấu nháy kép xử lý các ký tự thoát như \n; chuỗi thô trong dấu backquote thì không, và có thể trải dài nhiều dòng. Trang về chuỗi trình bày package strings, còn trang rune và byte nói sâu về UTF-8.

byte và rune

Bí danhGiống vớiChứa
byteuint8một byte dữ liệu thô
runeint32một code point Unicode

Đây là bí danh, không phải kiểu mới: byte và uint8 dùng thay cho nhau được mà không cần chuyển kiểu. Cái tên cho biết con số đó mang ý nghĩa gì.

Số phức

Go có sẵn các kiểu số phức, complex64 và complex128, cùng real, imag và package math/cmplx:

Ít chương trình cần đến chúng, nhưng xử lý tín hiệu và một số code tính toán số thì có.

Kiểu tổng hợp và kiểu tham chiếu

Các kiểu cơ bản kết hợp thành kiểu tổng hợp. Mỗi kiểu có trang riêng:

KiểuVí dụGiá trị zero
mảng[3]intba số 0
slice[]intnil
mapmap[string]intnil
structstruct{ X, Y int }mọi trường đều zero
con trỏ*intnil
hàmfunc(int) intnil
channelchan intnil
interfaceerror, anynil

any là bí danh của interface{} (từ Go 1.18) và chứa được giá trị thuộc bất kỳ kiểu nào.

Kiểu có tên

Bạn có thể định nghĩa một kiểu mới từ một kiểu có sẵn. Nó có cùng cách biểu diễn nhưng là một kiểu riêng biệt, và có thể có phương thức:

type Celsius float64
type UserID int64

var t Celsius = 21.5
var f float64 = t // compile error: cannot use t (variable of float64 type Celsius) as float64 value in variable declaration

Sự chặt chẽ đó chính là mục đích: không thể vô tình truyền một UserID vào chỗ cần OrderID. Hãy chuyển kiểu tường minh khi bạn thực sự muốn: float64(t). Xem trang chuyển đổi kiểu để biết các quy tắc và các hàm strconv để chuyển qua lại giữa số và chuỗi.

Giá trị zero

Mọi kiểu đều có giá trị zero, là thứ một biến chứa trước khi bạn gán gì cho nó: 0 cho số, false cho bool, "" cho chuỗi, và nil cho con trỏ, slice, map, channel, hàm và interface. Trong Go không có biến chưa khởi tạo.

Câu hỏi thường gặp

Kiểu int trong Go lớn bao nhiêu?

int và uint là 64 bit trên các nền tảng 64 bit (amd64, arm64) và 32 bit trên các nền tảng 32 bit. Nếu cần kích thước cố định, cho một định dạng tệp hay giao thức mạng, hãy dùng int32, int64, uint8 và các kiểu tương tự. Với bộ đếm, chỉ số và độ dài thông thường, dùng int.

In kiểu của một biến trong Go bằng cách nào?

Dùng verb %T: fmt.Printf("%T\n", x) in ra int, float64, []string, main.User và tương tự. Trong code, reflect.TypeOf(x) trả về cùng thông tin dưới dạng một giá trị mà bạn kiểm tra được.

byte và rune trong Go khác nhau thế nào?

byte là bí danh của uint8 và chứa một byte dữ liệu thô. rune là bí danh của int32 và chứa một code point Unicode. Chuỗi là một dãy byte; duyệt nó bằng for range sẽ giải mã nó thành các rune.

Nên dùng float32 hay float64 trong Go?

Dùng float64 trừ khi có lý do khác. Đây là kiểu mặc định của literal số thực, là kiểu package math làm việc cùng, và có độ chính xác khoảng 15 đến 17 chữ số thập phân có nghĩa, so với khoảng 6 đến 9 của float32. Chỉ chọn float32 để giảm một nửa bộ nhớ trong các mảng lớn hoặc để khớp với một định dạng bên ngoài.

Giá trị lớn nhất của int trong Go là bao nhiêu?

Dùng các hằng số trong package math: math.MaxInt (9223372036854775807 trên nền tảng 64 bit), math.MinInt, math.MaxInt64, math.MaxUint32 và tương tự. Phép tính vượt quá giới hạn sẽ âm thầm quay vòng lúc chạy; nó không gây panic.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu