Go並沒有類似JavaScript及Java lambda內建用來遍歷集合或陣列的forEach及依條件篩選陣列元素的filter,需要的時候只能自己用for迴圈實作。
範例環境:
- Go 1.16
struct Employee
和Department
在model
package。
model.go
package model
type Employee struct {
Id int
Name string
Age int
}
type Department struct {
Id int
Name string
Employees []Employee
}
下面getDeps()
用來產生[]Department
slice資料。
foreach()
負責遍歷slice,參數filter
函式用來篩選[]Department
符合條件的元素;
isAllEmpLess30()
為filter
函式的實例。
main.go
package main
import (
"fmt"
"abc.com/demo/model"
)
func main() {
deps := getDeps()
result := foreach(deps, isAllEmpLess30)
fmt.Println(result)
}
func getDeps() (deps []model.Department) {
deps = []model.Department{
{
Id: 1,
Name: "HR",
Employees: []model.Employee{
{Id: 1, Name: "John", Age: 33},
{Id: 2, Name: "Mary", Age: 28},
},
},
{
Id: 2,
Name: "Mkt.",
Employees: []model.Employee{
{Id: 3, Name: "Bill", Age: 18},
{Id: 4, Name: "Nick", Age: 17},
},
},
}
return
}
func foreach(deps []model.Department, filter func(dep model.Department) bool) (result []model.Department) {
for _, dep := range deps {
if filter(dep) {
result = append(result, dep)
}
}
return
}
func isAllEmpLess30(dep model.Department) bool {
emps := dep.Employees
if emps != nil && len(emps) != 0 {
for _, emp := range emps {
return !(emp.Age > 30)
}
}
return true
}
把foreach()
及函示參數filter
改成"Generic"一點(Go沒有泛型(Generic),需要利用空介面interface{}
和反射 package reflect
功能來替代),不過效能不好。
main.go
package main
import (
"fmt"
"reflect"
"abc.com/demo/model"
)
func main() {
deps := getDeps()
result := foreach(deps, func(o interface{}) bool {
dep, _ := o.(model.Department) // type assertion, convert interface to struct
emps := dep.Employees
if emps != nil && len(emps) != 0 {
for _, emp := range emps {
return !(emp.Age > 30)
}
}
return true
})
fmt.Println(result)
}
func getDeps() (deps []model.Department) {...}
func foreach(arr interface{}, filter func(o interface{}) bool) (result interface{}) {
typ := reflect.TypeOf(arr)
vals := reflect.ValueOf(arr)
for i := 0; i < vals.Len(); i++ {
if v := vals.Index(i); filter(v.Interface()) {
result = reflect.Append(reflect.MakeSlice(typ, 0, 0), v)
}
}
return
}
沒有留言:
張貼留言