Go có các kiểu tĩnh, mạnh và nó không hỗ trợ các kiểu chung, vậy làm thế nào chúng ta có thể xác định các cấu trúc dữ liệu mục đích chung và các thuật toán có thể áp dụng cho nhiều hơn một kiểu?interface{}
s không phải là giải pháp, vì chúng yêu cầu đúc và chúng tôi mất rất nhiều lợi thế của việc gõ tĩnh mạnh mẽ.Giải pháp là tạo mã, vì nó cho phép kiểm tra thời gian biên dịch và độ an toàn cũng như hiệu suất cao hơn.
Tôi không tìm thấy thông tin này dễ dàng truy cập khi tìm kiếm các chủ đề tạo mã, nhưng tôi đã vấp phải các trường hợp và tình huống sử dụng phức tạp hơn, vì vậy đây là nó, được giải thích bằng tiếng Anh đơn giản.
Vấn đề:
tôi muốntriển khai cấu trúc dữ liệu(điều tương tự cũng áp dụng cho một thuật toán)theo cách chung nhất có thểvới cờ vây vàtạo các triển khai loại cụ thể mà tôi có thể dễ dàng sử dụng lại.
Giải pháp:
Sử dụnggenny, điều này không thể đơn giản hơn:
- nhập khẩu
genny/generic
- xác định một hoặc nhiều loại dưới dạng
generic.Type
, ví dụ: gọi họItem
hoặc làType
- sử dụng những loại này trong mã của bạn
- chạy
genny
để tạo triển khai loại cụ thể
Thí dụ
Kiểm tra ví dụ đơn giản này, đây là phiên bản rút gọn củaĐặt triển khai Cấu trúc dữ liệu trong Go:
// Package set creates a ItemSet data structure for the Item type
package set
import “github.com/cheekybits/genny/generic”
// Item the type of the Set
type Item generic.Type
// ItemSet the set of Items
type ItemSet struct {
items map[Item]bool
}
// Add adds a new element to the Set. Returns the Set.
func (s ItemSet) Add(t Item) ItemSet {
if s.items == nil {
s.items = make(map[Item]bool)
}
_, ok := s.items[t]
if !ok {
s.items[t] = true
}
return s
}
// Clear removes all elements from the Set
func (s ItemSet) Clear() {
(s).items = make(map[Item]bool)
}
Bằng cách chạy
genny -in set.go -out gen-set.go gen "Item=string,int"
trong dòng lệnh ngay bây giờ, nếu tệp được gọiset.go
nó sẽ tạo ra mộtgen-set.go
trong đó có những thứ sau:
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
// Package Set creates a StringSet data structure for the string type
package set
// StringSet the set of Strings
type StringSet struct {
items map[string]bool
}
// Add adds a new element to the Set. Returns the Set.
func (s StringSet) Add(t string) StringSet {
s.items[t] = true
return s
}
// Clear removes all elements from the Set
func (s StringSet) Clear() {
(s).items = make(map[string]bool)
}
// Delete removes the string from the Set and returns Has(string)
func (s StringSet) Delete(item string) bool {
ret := (s).Has(item)
if ret {
delete((*s).items, item)
}
return ret
}
// Has returns true if the Set contains the string
func (s StringSet) Has(item string) bool {
return (s).items[item]
}
// Strings returns the string(s) stored
func (s *StringSet) Strings() []string {
items := []string{}
for i := range s.items {
items = append(items, i)
}
return items
}
// Package Set creates a IntSet data structure for the int type
// IntSet the set of Ints
type IntSet struct {
items map[int]bool
}
// Add adds a new element to the Set. Returns the Set.
func (s IntSet) Add(t int) IntSet {
s.items[t] = true
return s
}
// Clear removes all elements from the Set
func (s IntSet) Clear() {
(s).items = make(map[int]bool)
}
// Delete removes the int from the Set and returns Has(int)
func (s IntSet) Delete(item int) bool {
ret := (s).Has(item)
if ret {
delete((*s).items, item)
}
return ret
}
// Has returns true if the Set contains the int
func (s IntSet) Has(item int) bool {
return (s).items[item]
}
// Ints returns the int(s) stored
func (s *IntSet) Ints() []int {
items := []int{}
for i := range s.items {
items = append(items, i)
}
return items
}
Bạn có thể thấy,genny
đã tạo raStringSet
vàIntSet
cấu trúc từItemSet
**, vì đã nói với nóItem=string,int
.
Nó cũng tạo ra các phương thức cấu trúctạo ra các triển khai Set của chúng tôi.
Nếu chúng ta muốn thêm một tập hợp các loại khác vào ứng dụng của mình, chúng ta có thể chỉnh sửa lệnh và chạy lại.
Sử dụnggo generate
Bạn cũng có thể tự động hóa việc này bằng cách thêm nhận xét ở đầu tệp, bên dưới tài liệu gói, như:
// go:generate genny -in=$GOFILE -out=gen-$GOFILE gen "Item=string,int"
Điều này nói vớigo generate
, thông qua sự giúp đỡ củagenny
, để tạo một phiên bản dịchItem
đếnstring
và phiên bản thứ hai đang dịchitem
đếnint
.
Chạy
go generate
để có đượcgen-set.go
tệp, với chuỗi và tập hợp int.
Thử nghiệm
Quan trọng: triển khai chung của cấu trúc dữ liệu ở trênbiên dịch và có thể được kiểm tradễ dàng như một triển khai cụ thể được tạo ra bởigo generate
, vì vậy chúng tôi có thể chạy các thử nghiệm đối với việc triển khai chung của chúng tôi, cũng như các thử nghiệm dành riêng cho từng loại.
Các hướng dẫn về go khác:
- Sử dụng NGINX Reverse Proxy để phục vụ các dịch vụ Go
- Tạo bản sao của cấu trúc trong Go
- Khái niệm cơ bản về Máy chủ Web Go
- Sắp xếp loại bản đồ trong Go
- Tóm lại về con trỏ
- Giải thích về Thẻ Go
- Định dạng Ngày và Giờ
- Xử lý JSON với Go
- Đi các chức năng đa dạng
- Go Strings Cheat Sheet
- Giải thích về giao diện trống rỗng
- Gỡ lỗi Go với VS Code và Delve
- Named Go trả về các tham số
- Tạo chuỗi và số ngẫu nhiên trong Go
- Cấu trúc hệ thống tệp của một dự án Go
- Thuật toán tìm kiếm nhị phân được triển khai trong Go
- Sử dụng cờ dòng lệnh khi di chuyển
- GOPATH giải thích
- Xây dựng ứng dụng Dòng lệnh với Go: lolcat
- Xây dựng lệnh CLI với Go: coway
- Sử dụng Shell Pipes with Go
- Hướng dẫn về CLI: nhân bản may mắn
- Liệt kê các tệp trong một thư mục với Go
- Sử dụng Go để lấy danh sách các kho từ GitHub
- Tiếp tục, nối một đoạn chuỗi vào một tệp
- Chuyển đổi một chuỗi thành một lát byte
- Hình dung các đóng góp Git địa phương của bạn với Go
- Bắt đầu với Go cấu hình CPU và bộ nhớ
- Giải quyết lỗi "không hỗ trợ lập chỉ mục" trong chương trình Go
- Đo thời gian thực thi trong chương trình cờ vây
- Xây dựng Trình thu thập thông tin web với Go để phát hiện các tiêu đề trùng lặp
- Thực hiện các phương pháp hay nhất: Con trỏ hoặc bộ thu giá trị?
- Thực hiện các phương pháp hay nhất: Bạn nên sử dụng một phương pháp hay một hàm?
- Đi cấu trúc dữ liệu: Đặt
- Go Maps Cheat Sheet
- Tạo triển khai cho các loại chung trong Go
- Truy cập cấu trúc dữ liệu: Từ điển
- Truy cập cấu trúc dữ liệu: Bảng băm
- Triển khai sự kiện Người nghe trong Đi qua các Kênh
- Truy cập cấu trúc dữ liệu: Ngăn xếp
- Truy cập cấu trúc dữ liệu: Hàng đợi
- Đi cấu trúc dữ liệu: Cây tìm kiếm nhị phân
- Đi cấu trúc dữ liệu: Đồ thị
- Truy cập cấu trúc dữ liệu: Danh sách được liên kết
- Hướng dẫn đầy đủ về cấu trúc dữ liệu Go
- So sánh các giá trị Go
- Go có hướng đối tượng không?
- Làm việc với Cơ sở dữ liệu SQL trong Go
- Sử dụng các biến môi trường trong Go
- Xem hướng dẫn: REST API được hỗ trợ bởi PostgreSQL
- Bật CORS trên Máy chủ Web Go
- Triển khai ứng dụng Go trong Docker Container
- Tại sao Go là một ngôn ngữ mạnh mẽ để học với tư cách là một nhà phát triển PHP
- Đi, xóa ký tự dòng mới io.Reader.ReadString
- Bắt đầu, cách xem các thay đổi và xây dựng lại chương trình của bạn
- Đi, đếm tháng kể từ một ngày
- Truy cập thông số HTTP POST trong Go