Go by Example: Generics

Bắt đầu từ phiên bản 1.18, Go đã hỗ trợ thêm cho generics, also known as type parameters (tham số kiểu dữ liêu).

package main
import "fmt"

Một ví dụ về hàm generic, MapKeys nhận một map với bất kì kiểu nào và trả về một slices các key của nó. Hàm này có hai type parameters - KV; K có ràng buộc comparable (so sánh), nghĩa là chúng ta có thể so sánh các giá trị của kiểu này với toán tử ==!= . Điều này là

để sử dụng key trong map của Go.

V có ràng buộc any (bất kì), nghĩa là nó không bị hạn chết bởi bất kì đièu gì (any là một định danh khác cho interface{}).

func MapKeys[K comparable, V any](m map[K]V) []K {
    r := make([]K, 0, len(m))
    for k := range m {
        r = append(r, k)
    }
    return r
}

Một ví dụ về type (kiểu) generics là List, List là một danh sách liên kết đơn với các giá trị của bất kỳ kiểu dữ liệu nào.

type List[T any] struct {
    head, tail *element[T]
}
type element[T any] struct {
    next *element[T]
    val  T
}

Chúng ta có thể định nghĩa các phương thức trên generic types giống như các kiểu thông thường, nhưng chúng ta phải giữ các type parameters đúng vị trí. Kiểu này là List[T], không phải List.

func (lst *List[T]) Push(v T) {
    if lst.tail == nil {
        lst.head = &element[T]{val: v}
        lst.tail = lst.head
    } else {
        lst.tail.next = &element[T]{val: v}
        lst.tail = lst.tail.next
    }
}
func (lst *List[T]) GetAll() []T {
    var elems []T
    for e := lst.head; e != nil; e = e.next {
        elems = append(elems, e.val)
    }
    return elems
}
func main() {
    var m = map[int]string{1: "2", 2: "4", 4: "8"}

Khi gọi các hàm generic, chúng ta thường

    //có thể dựa vào _type inference_. Lưu ý rằng

chúng ta không cần phải xác định kiểu cho K and V khi gọi MapKeys - trình biên dịch sẽ tự động suy ra chúng

    fmt.Println("keys:", MapKeys(m))

… tuy nhiên, chúng ta cũng có thể xác định chúng một cách rõ ràng.

    lst := List[int]{}
    lst.Push(10)
    lst.Push(13)
    lst.Push(23)
    fmt.Println("list:", lst.GetAll())
}
$ go run generics.go
keys: [4 1 2]
list: [10 13 23]

Ví dụ tiếp theo: Errors.