嵌入式技术
作者:ShadowYD
关键字参数
众所周知很多语言的function 中都支持 key=word 关键字参数, 但 golang 是不支持的, 我们可以利用泛型去简单的实现.
func DefaultKeyWordParams[D any](defVal D, params ...D) D { if len(params) == 0 { return defVal } return params[0] } func test(category ...string) { // 不填写则返回默认值 realCategory := DefaultKeyWordParams[string]("AGroup", category...) fmt.Println(realCategory) } func main () { test() }
快速排序
UpdateAt: 2023-02-22
实现一个可进行控制反转的通用类型快速排序, 解决一下原生的sort包进行类型定义的繁琐.
// QuickSort 通用快速排序 func QuickSort[T any](arr []T, compareFn func(a, b T) bool) { if len(arr) < 2 { return } pivot := arr[0] left := 1 right := len(arr) - 1 for left <= right { if compareFn(arr[left], pivot) { left++ } else if compareFn(pivot, arr[right]) { right-- } else { arr[left], arr[right] = arr[right], arr[left] } } arr[0], arr[right] = arr[right], arr[0] QuickSort(arr[:right], compareFn) QuickSort(arr[right+1:], compareFn) }
测试用例
func TestQuickSort(t *testing.T) { nums := []int{9, 3, 1, 7, 4, 8, 6, 2, 5} fmt.Println("Unsorted:", nums) QuickSort[int](nums, func(a, b int) bool { return a < b }) fmt.Println("Sorted: ", nums) strs := []string{"orange", "apple", "banana", "kiwi", "grape"} fmt.Println("Unsorted:", strs) QuickSort[string](strs, func(a, b string) bool { return len(a) < len(b) }) fmt.Println("Sorted: ", strs) }
去重复
这是一个简单的实现, 复杂点可以通过回调 + 泛型来实现;
func RemoveDuplicate[T string | int | float64](duplicateSlice []T) []T { set := map[T]interface{}{} res := []T{} for _, item := range duplicateSlice { _, ok := set[item] if !ok { res = append(res, item) set[item] = nil } } return res } func main() { fmt.Println(RemoveDuplicate[string]([]string{"a", "c", "a"})) fmt.Println(RemoveDuplicate[int]([]int{1, 2, 1, 1, 1})) }
通过控制反转实现通用的去重复方法, 支持任意类型;
type Student struct { Name string Age int } func NewStudent(name string, age int) *Student { return &Student{Name: name, Age: age} } func DefaultFilter(item interface{}) (uniqueKey interface{}) { return item.(*Student).Name } func RemoveDuplicateWithFilter[T comparable](compareSlice []T, filterFunc func(item interface{}) (key interface{})) []T { set := map[interface{}]interface{}{} res := []T{} for _, item := range compareSlice { i := filterFunc(item) _, ok := set[i] if !ok { res = append(res, item) set[i] = nil } } return res } func main() { s := []*Student{ NewStudent("a", 1), NewStudent("a", 1), NewStudent("b", 2), NewStudent("b", 2), } l := RemoveDuplicateWithFilter[*Student](s, DefaultFilter) for _, i := range l { fmt.Println(i.Name, i.Age) } }
联合约束类型
该例子只是一个演示, 没有实际效果
type ID interface { int | string } // 写法 [T ID, D string] == [T int | string, D string] type UserModel[T ID, D string] struct { Id T Name D } func NewUserModel[A ID, D string](id A, name D) *UserModel[A, D] { return &UserModel[A, D]{Id: id, Name: name} } func main() { fmt.Println(NewUserModel[int, string](10, "hello")) fmt.Println(NewUserModel[string, string]("10", "hello")) }
分页
这是一段线上在使用的分页代码, 当无法使用外部存储器进行分页时直接使用该对象进行分页, 支持任意类型;
type KeepItem bool // 若需要保留的item 则返回true 即可 type FilterFunc func(item interface{}) KeepItem type PageList[T any] struct { Total int `json:"total"` Page int `json:"page"` Size int `json:"size"` List []T `json:"list"` } type Pager[T any] struct { limit int offset int total int pageCnt int list []T } func NewPager[T any](list []T) *Pager[T] { return &Pager[T]{ limit: 10, offset: 1, total: len(list), list: list, } } func (this *Pager[T]) Filter(filterFn FilterFunc) *Pager[T] { tmpList := []T{} for _, item := range this.list { if filterFn(&item) { tmpList = append(tmpList, item) } } this.list = tmpList this.total = len(tmpList) return this } func (this *Pager[T]) Offset(c int) *Pager[T] { this.offset = c return this } func (this *Pager[T]) Limit(c int) *Pager[T] { this.limit = c return this } func (this *Pager[T]) List() []T { // 页码 if this.offset <= 0 { this.offset = 1 } // size if this.limit > this.total { this.limit = this.total } // 总页数 this.pageCnt = int(math.Ceil(float64(this.total) / float64(this.limit))) if this.offset > this.pageCnt { return []T{} } startIdx := (this.offset - 1) * this.limit endIdx := startIdx + this.limit if endIdx > this.total { endIdx = this.total } return this.list[startIdx:endIdx] } func (this *Pager[T]) Output() *PageList[T] { return &PageList[T]{ Total: this.total, Page: this.offset, Size: this.limit, List: this.list, } } // test func main () { page := NewPager[int]([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) list := page.Offset(1).Limit(3).Filter(func(item interface{}) KeepItem { if *item.(*int)%2 == 1 { return true } return false }).List() fmt.Println(list) }
通用初始化模型
可以解决在多态下使用同一个初始化函数进行对象初始化, 写法上有点绕大家自行多实验几次就能明白.
type ModelObj interface { User | Product } type User struct { Uid int } func (this *User) SetId(id int) { this.Uid = id } type Product struct { Pid int } func (this *Product) SetId(id int) { this.Pid = id } // TrimModelObj 是一个动态类型的 Interface, 由M决定当前Interface的最终类型 type TrimModelObj[M ModelObj] interface { *M SetId(id int) } // TrimModelObj[Model] 由第二个参数决定当前的动态类型; // NewModelObj[*User, User](32) 如 Model 是 User 类型, 最终 TrimModelObj == *User,所以我们需要为 Trim 传递 *User func NewModelObj[Trim TrimModelObj[Model], Model ModelObj](id int) Trim { m := new(Model) t := Trim(m) fmt.Printf("%p ", m) // 类型转换成指定的*Model t.SetId(id) return t } func main() { // new user model object user := NewModelObj[*User, User](32) fmt.Printf("%p ", user) fmt.Printf("%T ", user) fmt.Println(user.Uid) // new product model object prod := NewModelObj[*Product, Product](18) fmt.Printf("%p ", prod) fmt.Printf("%T ", prod) fmt.Println(prod.Pid) }
全部0条评论
快来发表一下你的评论吧 !