Struct trong Go - Cách tổ chức dữ liệu thông minh! 🏗️
Chào mừng bạn đến với bài học về struct trong Go! Giống như một hồ sơ cá nhân, struct giúp chúng ta tổ chức thông tin liên quan đến nhau một cách gọn gàng. Trong bài học này, chúng ta sẽ tìm hiểu cách tạo và sử dụng struct một cách hiệu quả.
Struct là gì? 🤔
Giống như một hồ sơ cá nhân:
- Có nhiều thông tin khác nhau
- Các thông tin liên quan đến nhau
- Dễ dàng quản lý và sử dụng
1. Khai báo struct cơ bản (Tạo mẫu hồ sơ) 📝
type Person struct {
Name string
Age int
Email string
}
💡 Giải thích:
type Person
: Tên của hồ sơstruct
: Đây là một hồ sơ- Các trường: Thông tin cần lưu
2. Struct với tags (Hồ sơ có nhãn) 🏷️
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Password string `json:"-"`
CreatedAt string `json:"created_at"`
}
💡 Giải thích:
json:"id"
: Tên khi chuyển thành JSONjson:"-"
: Không hiển thị trong JSON- Giúp chuyển đổi dữ liệu dễ dàng
3. Struct lồng nhau (Hồ sơ trong hồ sơ) 📂
type Address struct {
Street string
City string
Country string
}
type Person struct {
Name string
Age int
Address Address
}
💡 Giải thích:
Address
: Một hồ sơ conPerson
: Hồ sơ chính chứa hồ sơ con- Giúp tổ chức thông tin phức tạp
Tạo và sử dụng Struct 🎯
1. Tạo instance (Tạo hồ sơ mới)
// Cách 1: Tạo và điền thông tin
person := Person{
Name: "John Doe",
Age: 30,
Email: "[email protected]",
}
// Cách 2: Tạo trống
person := Person{}
// Cách 3: Tạo với new
person := new(Person)
💡 Giải thích:
- Cách 1: Điền đầy đủ thông tin
- Cách 2: Tạo trống, thông tin sẽ là giá trị mặc định
- Cách 3: Tạo với con trỏ
2. Truy cập trường (Đọc và sửa thông tin)
// Đọc và sửa trực tiếp
person.Name = "Jane Doe"
age := person.Age
// Đọc và sửa qua con trỏ
p := &person
p.Name = "Jane Doe"
💡 Giải thích:
.
: Dùng để truy cập thông tin&
: Lấy địa chỉ của hồ sơ*
: Truy cập qua con trỏ
Method (Hàm đặc biệt cho struct) 🛠️
1. Method với value receiver
func (p Person) String() string {
return fmt.Sprintf("%s (%d)", p.Name, p.Age)
}
💡 Giải thích:
(p Person)
: Hàm này dành cho hồ sơ PersonString()
: Tên của hàm- Trả về chuỗi mô tả hồ sơ
2. Method với pointer receiver
func (p *Person) SetAge(age int) {
p.Age = age
}
💡 Giải thích:
(p *Person)
: Hàm này dành cho con trỏ PersonSetAge
: Thay đổi tuổi- Dùng con trỏ để sửa thông tin
3. Method với interface
type Stringer interface {
String() string
}
💡 Giải thích:
interface
: Định nghĩa các hàm cần cóString()
: Hàm bắt buộc- Giúp chuẩn hóa cách hiển thị
Struct với Interface (Hồ sơ đa năng) 🎨
type Shape interface {
Area() float64
}
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
💡 Giải thích:
Shape
: Interface định nghĩa cách tính diện tíchRectangle
vàCircle
: Các hồ sơ khác nhau- Mỗi hồ sơ có cách tính diện tích riêng
Struct với JSON (Chuyển đổi dữ liệu) 🔄
Marshal (Chuyển thành JSON)
type User struct {
ID int `json:"id"`
Username string `json:"username"`
}
func main() {
user := User{
ID: 1,
Username: "john",
}
data, err := json.Marshal(user)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
}
💡 Giải thích:
json.Marshal
: Chuyển hồ sơ thành JSONjson:"id"
: Định dạng khi chuyển đổi- Xử lý lỗi nếu có
Best Practices (Cách sử dụng tốt) 🌟
1. Đặt tên struct rõ ràng
// ✅ Tốt
type CustomerProfile struct {
Name string
Address string
}
// ❌ Không tốt
type CP struct {
N string
A string
}
💡 Lý do: Giúp người khác dễ hiểu mục đích
2. Sử dụng tags hợp lý
// ✅ Tốt
type User struct {
ID int `json:"id" validate:"required"`
Username string `json:"username" validate:"min=3"`
}
// ❌ Không tốt
type User struct {
ID int `json:"i"`
Username string `json:"u"`
}
💡 Lý do: Giúp chuyển đổi và kiểm tra dữ liệu
3. Tổ chức struct hợp lý
// ✅ Tốt
type Address struct {
Street string
City string
Country string
}
type Person struct {
Name string
Age int
Address Address
}
// ❌ Không tốt
type Person struct {
Name string
Age int
Street string
City string
Country string
}
💡 Lý do: Giúp code dễ đọc và bảo trì
Những lỗi thường gặp và cách sửa 🔧
-
Lỗi: Quên khởi tạo struct
// ❌ Sai
var person Person
person.Name = "John" // OK
person.Age = 30 // OK
person.Email = "" // OK
// ✅ Đúng
person := Person{
Name: "John",
Age: 30,
Email: "[email protected]",
} -
Lỗi: Sử dụng con trỏ không cần thiết
// ❌ Sai
func (p *Person) GetName() string {
return p.Name
}
// ✅ Đúng
func (p Person) GetName() string {
return p.Name
} -
Lỗi: Quên xử lý lỗi khi chuyển đổi JSON
// ❌ Sai
data, _ := json.Marshal(user)
// ✅ Đúng
data, err := json.Marshal(user)
if err != nil {
return err
}
Tiếp theo 🎯
Trong bài học tiếp theo, chúng ta sẽ:
- Tìm hiểu về interfaces (giao diện)
- Học cách xử lý lỗi nâng cao
- Khám phá cách sử dụng goroutines
💡 Lời khuyên: Hãy thử tạo các struct đơn giản và thêm các method để hiểu rõ hơn về cách chúng hoạt động!