Go Zero to Hero - Bài 8: Ép kiểu (Type Casting) trong Golang
Trong lập trình Backend, việc xử lý dữ liệu đến từ nhiều nguồn khác nhau (Database, HTTP Request, JSON payload) đòi hỏi bạn phải thao tác với việc ép kiểu dữ liệu liên tục. Triết lý của Go đối với việc này là tuyệt đối an toàn và rõ ràng.
1. Sự khắt khe của Go: Không có ép kiểu ngầm định
Quy tắc tối thượng trong Go: Không bao giờ có chuyện tự động ép kiểu giữa các biến khác loại, dù chúng có họ hàng gần với nhau đi chăng nữa.
Hãy xem thử đoạn code sau, trông rất bình thường nhưng sẽ khiến trình biên dịch của Go "nổi điên":
func main() {
var a int = 10
var b float64 = 5.5
// LỖI! Invalid operation: a + b (mismatched types int and float64)
var sum = a + b
}
Go sẽ không tự động biến a thành float64 để cộng với b. Nó bắt bạn phải nói rõ: "Tôi muốn biến a thành kiểu số thực rồi mới cộng". Sự khắt khe này giúp hệ thống của bạn triệt tiêu hoàn toàn những bug tiềm ẩn liên quan đến sai số hay tràn bộ nhớ ở thời điểm Runtime.
2. Type Conversion: Ép kiểu cơ bản (Cú pháp T(v))
Để ép kiểu một giá trị v sang kiểu dữ liệu T, Go sử dụng cú pháp rất đơn giản: T(v).
Quay lại ví dụ trên, để đoạn code chạy được, bạn phải ép kiểu rõ ràng:
func main() {
var a int = 10
var b float64 = 5.5
// Cách 1: Ép int sang float64
var sum1 float64 = float64(a) + b // Kết quả: 15.5
// Cách 2: Ép float64 sang int
var sum2 int = a + int(b) // Kết quả: 15 (Số 5.5 bị cắt mất phần thập phân)
}
⚠️ Lưu ý sinh tử: Khi bạn ép kiểu từ vùng nhớ lớn xuống vùng nhớ nhỏ (ví dụ từ
int64xuốngint8), nếu giá trị vượt quá giới hạn củaint8(từ -128 đến 127), dữ liệu sẽ bị tràn (overflow) và sinh ra một con số vô nghĩa. Hãy luôn cẩn thận khi ép kiểu xuống (Down-casting)!
3. Chuyển đổi qua lại với Chuỗi: Gói strconv
Trong thực tế làm Backend API, dữ liệu bạn nhận được từ Client (qua Query Params, JSON body) thường nằm ở dạng Chuỗi (string). Làm sao để biến "100" thành số 100? Bạn không thể dùng cú pháp int("100") được.
Đó là lúc gói thư viện tiêu chuẩn strconv (String Conversion) tỏa sáng.
Chuỗi sang Số (String to Int/Float)
Hàm được dùng nhiều nhất là strconv.Atoi (ASCII to Integer).
package main
import (
"fmt"
"strconv"
)
func main() {
strPrice := "250000"
// Hàm Atoi trả về 2 giá trị: kết quả (số int) và lỗi (error)
price, err := strconv.Atoi(strPrice)
if err != nil {
fmt.Println("Chuỗi không phải là số hợp lệ!")
} else {
fmt.Println("Giá tiền:", price)
}
}
Để chuyển chuỗi sang số thập phân, bạn dùng strconv.ParseFloat():
piString := "3.14159"
piFloat, _ := strconv.ParseFloat(piString, 64) // 64 là đại diện cho float64
Số sang Chuỗi (Int/Float to String)
Ngược lại với Atoi, chúng ta có hàm Itoa (Integer to ASCII):
userID := 9981
strID := strconv.Itoa(userID) // Kết quả: "9981"
4. Type Assertion: Ép kiểu với interface{}
(Mặc dù chúng ta chưa học sâu về Interface, nhưng đây là một khái niệm bạn sẽ gặp ngay khi làm việc với JSON hay các thư viện ngoài).
Trong Go, interface{} (hoặc any từ Go 1.18) là một kiểu dữ liệu có thể chứa BẤT KỲ thứ gì (int, string, struct...). Khi bạn nhận một biến kiểu interface{}, bạn cần phải "khẳng định" (assert) kiểu thực sự của nó trước khi sử dụng.
Cú pháp: value, ok := variable.(Type)
func main() {
var rawData interface{} = "Đây là một chuỗi"
// Khẳng định rawData là kiểu string
text, ok := rawData.(string)
if ok {
fmt.Println("Đã ép kiểu thành công:", text)
} else {
fmt.Println("Ép kiểu thất bại, đây không phải là string")
}
}
Chốt chặn an toàn: Biến
ok(kiểu boolean) là một chốt chặn an toàn cực hay của Go. NếurawDatakhông phải là chuỗi,oksẽ trả vềfalsevà chương trình vẫn chạy bình thường. Nếu bạn viết tắttext := rawData.(string)mà dữ liệu thực tế lại là số nguyên, chương trình của bạn sẽ bị Panic (Crash sập server) ngay lập tức.
Tổng kết
Tóm lại, tư duy xử lý kiểu dữ liệu trong Go có thể gói gọn trong 3 ý:
- Chủ động và Rõ ràng: Mọi sự chuyển đổi kiểu dữ liệu cơ bản đều dùng cú pháp
T(v). - Làm bạn với
strconv: Bất cứ khi nào cần biến Chuỗi thành Số hoặc ngược lại, hãy nhớimportgóistrconv. - An toàn là trên hết: Khi làm việc với
interface{}, luôn dùng cặpvalue, okđể kiểm tra Type Assertion, tuyệt đối không chủ quan để ứng dụng bị crash.
All Rights Reserved