Go Generics: Patterns thực tế cho code tái sử dụng

Go Generics ra mắt Go 1.18 cho phép viết code tái sử dụng với type parameters thay vì interface{} + reflection. Trước generics, lập trình viên Go phải viết lại hàm cho mỗi kiểu dữ liệu, dẫn đến code trùng lặp hoặc chấp nhận runtime overhead. Go generics giải quyết triệt để vấn đề này tại compile time, giữ performance tĩnh của Go.

Type Parameters cơ bản

Go generics giới thiệu type parameter list trong ngoặc vuông sau tên hàm hoặc kiểu. Cú pháp:

func Map[T any, U any](s []T, f func(T) U) []U

Hàm Map nhận slice bất kỳ kiểu T, áp dụng hàm f, trả slice kiểu U. any là alias cho interface{} — không ràng buộc kiểu. Compiler sinh mã riêng cho mỗi cặp (T, U) cụ thể được gọi.

Constraints

Ngoài any, Go cung cấp predeclared constraints: comparable (có thể so sánh bằng == hoặc !=), ordered (có thể so sánh < >), và custom interface. Ví dụ constraint cho type có phương thức String():

type Stringer interface { String() string }

Code example Go generics function syntax với type parameters và constraints

Patterns thực tế cho code tái sử dụng

1. Generic Map / Filter / Reduce

Trước generics, bạn dùng reflect hoặc viết lại MapInt, MapString. Bây giờ một hàm duy nhất:

func Filter[T any](s []T, pred func(T) bool) []T

Filter slice bất kỳ kiểu bằng predicate. Compiler tối ưu hóa, không reflection.

2. Generic Queue / Stack

Container type-safe mà không cần interface{}:

type Stack[T any] struct { items []T }

Stack ép kiểu tại compile time. Pop/Push không cần type assertion.

3. Generic Error Wrapping

Hàm Wrap[T error](err error, msg string) T hoặc generic Result[T] kiểu Rust. Không cần định nghĩa IntError, StrError riêng.

Biểu đồ so sánh code trước và sau generics: function duplication vs generic single implementation

Type Inference

Go compiler suy luận type arguments từ context. Map(s, func(i int) int { return i * 2 }) — compiler biết T=int từ kiểu slice s. Không cần ghi Map[int, int](s, ...) trừ khi compiler không suy luận được.

Inline và khi nào dùng

Go compiler inline generic functions. Performance gần với code tường minh. Dùng generics khi:

  • Container cần type-safe (slice, map, tree, queue).
  • Hàm thuật toán chung (Map, Filter, Reduce, Sort).
  • Interface chỉ dùng cho 1-2 hàm (thay vì interface lớn).

Khi nào KHÔNG dùng

Đừng abuse generics. Tránh generic cho:

  • Logic business chỉ áp dụng 1 kiểu cụ thể.
  • Interface có nhiều method, nên define concrete type rõ ràng.
  • Code đọc khó vì type parameter quá phức tạp (type inference mất, bug khó trace).

So sánh với Rust / C++ templates

Go generics an toàn hơn: không code bloat, không SFINAE, không specialization phức tạp. Rust có monomorphization + trait system mạnh hơn, nhưng complexity cao. Go generics giữ “boring” — compile, fail nếu không match, không template metaprogramming.

Kết luận

Go generics là bước ngoặt giúp codebase Go sạch hơn, DRY hơn mà vẫn giữ performance tĩnh. Học pattern căn bản: type parameters, constraints, type inference, container generic. Áp dụng vào Map/Filter/Reduce, Queue, Result — những nơi interface{} đang gây pain point. Dùng đúng mục đích, generics sẽ giảm boilerplate đáng kể mà không làm mất đi tính đơn giản của Go.

Nguồn: Go Blog – Generics in Go 1.18, Go Blog – When to Use Generics, Go Spec – Type Parameters

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

Programming code on computer screen showing Zig language

Zig: Ngôn Ngữ Lập Trình Hệ Thống Thay Thế C Với An Toàn Bộ Nhớ

Zig là ngôn ngữ lập trình hệ thống được tạo bởi Andrew Kelley, chính thức ra mắt năm 2016 sau nhiều năm phát triển. Zig hướng tới thay thế C…

Xem thêm

React Native: Phát Triển Ứng Dụng Đa Nền Tảng Bằng JavaScript

React Native: Phát Triển Ứng Dụng Đa Nền Tảng Bằng JavaScript React Native: Phát Triển Ứng Dụng Đa Nền Tảng Bằng JavaScript React Native cho phép xây dựng ứng dụng…

Xem thêm

Vite 6 là gì?

Vite 6 là gì? Vite 6 là công cụ build (build tool) và dev server thế hệ mới cho frontend JavaScript. Created bởi Evan You (creator of Vue.js), Vite leverages…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất