Struct ẩn danh
Thuộc phần Lập trình hướng đối tượng trong hành trình GO của Coddy. Bài học 15 trên 107.
struct ẩn danh là một struct không có kiểu được đặt tên. Bạn xác định cấu trúc và tạo một instance trong một bước mà không dùng từ khóa type.
person := struct {
Name string
Age int
}{
Name: "Alice",
Age: 30,
}Cách này tạo trực tiếp một giá trị struct mà không cần khai báo kiểu có thể tái sử dụng. Struct ẩn danh rất hữu ích khi bạn cần một cấu trúc dữ liệu dùng một lần, nhanh chóng và không dùng ở nơi khác trong code.
Một trường hợp thường gặp là nhóm các dữ liệu liên quan cho một hàm (function) hoặc bài kiểm thử.
config := struct {
Host string
Port int
}{
Host: "localhost",
Port: 8080,
}
fmt.Println(config.Host) // localhostStruct ẩn danh cũng thường được dùng trong các bài kiểm thử theo bảng, nơi mỗi test case có các trường riêng.
tests := []struct {
input int
expected int
}{
{1, 2},
{5, 10},
}Vì struct ẩn danh không có tên kiểu dữ liệu, bạn không thể định nghĩa phương thức cho chúng hoặc dùng lại kiểu dữ liệu đó ở nơi khác. Hãy dùng chúng để nhóm dữ liệu tạm thời trong phạm vi cục bộ. Với dữ liệu bạn sẽ tham chiếu nhiều lần, hãy định nghĩa một kiểu struct có tên.
Thử thách
DễHãy xây dựng một hệ thống cấu hình đơn giản để minh họa khi nào struct ẩn danh phát huy tác dụng, khi cần nhóm dữ liệu chỉ dùng một lần và không cần kiểu dữ liệu có thể tái sử dụng.
Bạn sẽ tổ chức code trong hai tệp:
config.go: Tạo một hàm có tênGetServerConfig, nhận tên máy chủ (chuỗi), cổng (số nguyên) và chế độ gỡ lỗi (boolean) làm tham số. Hàm này sẽ trả về một struct ẩn danh chứa ba giá trị dưới dạng các trường:Name,PortvàDebug. Vì cấu hình này chỉ được dùng ở một nơi nên bạn không cần định nghĩa kiểu có tên cho nó.main.go: Đọc các giá trị cấu hình máy chủ từ đầu vào, gọi hàmGetServerConfigvà hiển thị thông tin chi tiết về cấu hình.
Đầu vào sẽ gồm:
- Dòng 1: Tên máy chủ
- Dòng 2: Số cổng
- Dòng 3: Chế độ gỡ lỗi (
truehoặcfalse)
Định dạng đầu ra:
Server: [Name]
Port: [Port]
Debug: [Debug]Ví dụ, với đầu vào là api-server, 8080 và true, đầu ra của bạn sẽ là:
Server: api-server
Port: 8080
Debug: trueLưu ý cách struct ẩn danh giúp bạn trả về dữ liệu được nhóm lại mà không làm codebase thêm rườm rà với một kiểu chỉ được dùng một lần.
Tự làm thử
package main
import (
"fmt"
)
func main() {
// Đọc các giá trị đầu vào
var name string
var port int
var debug bool
fmt.Scanln(&name)
fmt.Scanln(&port)
fmt.Scanln(&debug)
// TODO: Gọi GetServerConfig với các giá trị đầu vào
// và lưu struct ẩn danh mà hàm trả về
// TODO: In cấu hình theo đúng định dạng yêu cầu:
// Server: [Name]
// Port: [Port]
// Debug: [Debug]
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng OOP trong Go
Tệp bên ngoàiWorkspace và module trong GoPackage và importTên được export và không được exportGiới thiệu về OOP trong GoStruct như lớpĐịnh nghĩa phương thức cho structReceiver kiểu con trỏ và kiểu giá trịKhởi tạo structHàm khởi tạoÔn tập: máy tính đơn giản4Interface
Giới thiệu về interfaceTriển khai ngầm địnhInterface như một hợp đồngInterface rỗng (any)Khẳng định kiểuswitch kiểuKết hợp interfaceInterface Stringer và ErrorÔn tập: Máy tính hình học7Tính đóng gói
Trường được xuất và không được xuấtĐóng gói ở cấp packagePhương thức getter và setterẨn thông tin trong GoÔn tập: hồ sơ học sinh10Generics (Go 1.18 trở lên)
Giới thiệu về GenericsTham số kiểuRàng buộc kiểuStruct tổng quátGiải pháp thay thế cho phương thức tổng quátÔn tập: tập hợp tổng quát13Các mẫu thiết kế phần 1
Giới thiệu về mẫu thiết kếMẫu SingletonMẫu FactoryMẫu Abstract FactoryMẫu ObserverMẫu Strategy2Tìm hiểu chuyên sâu về kiểu dữ liệu và struct
Kiểu cơ bản và kiểu tổng hợpĐịnh nghĩa kiểu dữ liệu tùy chỉnhThẻ structStruct ẩn danhStruct lồng nhauGiá trị zero và giá trị mặc địnhÔn tập: sổ liên lạc5Ưu tiên kết hợp hơn kế thừa
Vì sao Go không có kế thừaNhập môn nhúng structTự động nâng phương thứcNhúng nhiều structNhúng và kết tậpChe khuất phương thức được nhúngÔn tập: hệ phân cấp nhân viên8Xử lý lỗi và lập trình hướng đối tượng
Giao diện errorCác kiểu lỗi tùy chỉnhBọc lỗi với fmt.ErrorfLỗi sentinelerrors.Is() và errors.As()Panic, defer và recoverÔn tập: trình phân tích tệp3Con trỏ và bộ nhớ
Cơ bản về con trỏ trong GoCon trỏ đến structTruyền theo giá trị và tham chiếuHàm new()Thu gom rác trong GoÔn tập: xây dựng danh sách liên kết6Đa hình trong Go
Đa hình qua interfaceĐịnh kiểu vịt trong GoQuy tắc thỏa mãn interfaceCác tập hợp đa hìnhTiêm phụ thuộcÔn tập: bộ xử lý thanh toán9Lập trình đồng thời và lập trình hướng đối tượng
Cơ bản về goroutineChannel và giao tiếpChannel có bộ đệm và không có bộ đệmCâu lệnh selectsync.Mutex và sync.RWMutexsync.WaitGroupThiết kế struct an toàn luồngÔn tập: worker poolTự luyện tập: Trình biên dịch Go online