【go】函数类型的作用
Go 语言函数类型的巧妙应用
函数类型在 Go 语言中非常强大,允许将函数作为值进行传递和操作。下面详细介绍函数类型的各种妙用:
1. 回调函数
// 定义一个函数类型
type Callback func(int) int
// 接受回调函数的函数
func processData(data []int, callback Callback) []int {
result := make([]int, len(data))
for i, v := range data {
result[i] = callback(v)
}
return result
}
// 使用示例
func main() {
numbers := []int{1, 2, 3, 4, 5}
// 使用匿名函数作为回调
doubled := processData(numbers, func(x int) int {
return x * 2
})
// 使用已定义函数作为回调
squared := processData(numbers, square)
fmt.Println(doubled) // [2 4 6 8 10]
fmt.Println(squared) // [1 4 9 16 25]
}
func square(x int) int {
return x * x
}
2. 策略模式实现
type PaymentStrategy func(amount float64) bool
func processPayment(amount float64, strategy PaymentStrategy) bool {
return strategy(amount)
}
// 各种支付策略
func creditCardPayment(amount float64) bool {
// 信用卡支付逻辑
return true
}
func alipayPayment(amount float64) bool {
// 支付宝支付逻辑
return true
}
// 使用示例
func pay(amount float64, paymentMethod string) bool {
switch paymentMethod {
case "credit":
return processPayment(amount, creditCardPayment)
case "alipay":
return processPayment(amount, alipayPayment)
default:
return false
}
}
3. 装饰器模式
type HttpHandler func(w http.ResponseWriter, r *http.Request)
// 日志装饰器
func LoggingDecorator(handler HttpHandler) HttpHandler {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("Request: %s %s\n", r.Method, r.URL.Path)
handler(w, r)
fmt.Println("Request completed")
}
}
// 认证装饰器
func AuthDecorator(handler HttpHandler) HttpHandler {
return func(w http.ResponseWriter, r *http.Request) {
// 检查认证信息
if authenticate(r) {
handler(w, r)
} else {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
}
}
}
// 使用装饰器
func main() {
http.HandleFunc("/api/data", LoggingDecorator(AuthDecorator(handleData)))
http.ListenAndServe(":8080", nil)
}
func handleData(w http.ResponseWriter, r *http.Request) {
// 业务逻辑
}
4. 函数选项模式
type Server struct {
host string
port int
timeout time.Duration
maxConn int
}
type ServerOption func(*Server)
// 创建Server的选项函数
func WithHost(host string) ServerOption {
return func(s *Server) {
s.host = host
}
}
func WithPort(port int) ServerOption {
return func(s *Server) {
s.port = port
}
}
func WithTimeout(timeout time.Duration) ServerOption {
return func(s *Server) {
s.timeout = timeout
}
}
func WithMaxConn(maxConn int) ServerOption {
return func(s *Server) {
s.maxConn = maxConn
}
}
// 创建服务器
func NewServer(options ...ServerOption) *Server {
// 设置默认值
server := &Server{
host: "localhost",
port: 8080,
timeout: 30 * time.Second,
maxConn: 100,
}
// 应用所有选项
for _, option := range options {
option(server)
}
return server
}
// 使用示例
func main() {
server := NewServer(
WithHost("example.com"),
WithPort(9000),
WithTimeout(60 * time.Second),
)
// 使用server...
}
5. 中间件链
type Middleware func(http.Handler) http.Handler
// 中间件链
func Chain(middlewares ...Middleware) Middleware {
return func(next http.Handler) http.Handler {
for i := len(middlewares) - 1; i >= 0; i-- {
next = middlewares[i](next)
}
return next
}
}
// 使用示例
func main() {
handler := http.HandlerFunc(finalHandler)
// 创建中间件链
chain := Chain(
loggingMiddleware,
authMiddleware,
rateLimitMiddleware,
)
// 应用中间件链
http.Handle("/api", chain(handler))
http.ListenAndServe(":8080", nil)
}
6. 延迟执行与钩子函数
type ShutdownHook func()
type App struct {
shutdownHooks []ShutdownHook
}
func (a *App) AddShutdownHook(hook ShutdownHook) {
a.shutdownHooks = append(a.shutdownHooks, hook)
}
func (a *App) Shutdown() {
// 按照注册顺序的相反顺序执行钩子
for i := len(a.shutdownHooks) - 1; i >= 0; i-- {
a.shutdownHooks[i]()
}
}
// 使用示例
func main() {
app := &App{}
// 注册数据库关闭钩子
app.AddShutdownHook(func() {
fmt.Println("关闭数据库连接")
})
// 注册文件清理钩子
app.AddShutdownHook(func() {
fmt.Println("清理临时文件")
})
// 应用运行...
// 关闭应用
app.Shutdown()
}
7. 操作集合的函数
type FilterFunc func(int) bool
type MapFunc func(int) int
type ReduceFunc func(int, int) int
// 过滤集合
func Filter(nums []int, filter FilterFunc) []int {
result := []int{}
for _, n := range nums {
if filter(n) {
result = append(result, n)
}
}
return result
}
// 映射集合
func Map(nums []int, mapper MapFunc) []int {
result := make([]int, len(nums))
for i, n := range nums {
result[i] = mapper(n)
}
return result
}
// 归约集合
func Reduce(nums []int, initialValue int, reducer ReduceFunc) int {
result := initialValue
for _, n := range nums {
result = reducer(result, n)
}
return result
}
// 使用示例
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// 过滤偶数
evens := Filter(numbers, func(n int) bool {
return n%2 == 0
})
// 将数字翻倍
doubled := Map(evens, func(n int) int {
return n * 2
})
// 求和
sum := Reduce(doubled, 0, func(acc, n int) int {
return acc + n
})
fmt.Println("结果:", sum) // 60
}
8. 依赖注入
type UserRepository interface {
FindByID(id int) (User, error)
}
type UserService struct {
repo UserRepository
}
func NewUserService(repo UserRepository) *UserService {
return &UserService{repo: repo}
}
// 测试时可以轻松注入模拟实现
func TestUserService(t *testing.T) {
mockRepo := &MockUserRepository{
FindByIDFunc: func(id int) (User, error) {
return User{ID: id, Name: "测试用户"}, nil
},
}
service := NewUserService(mockRepo)
// 测试 service...
}
9. 自定义排序
type Person struct {
Name string
Age int
}
type SortBy func(p1, p2 *Person) bool
type PersonSorter struct {
people []Person
less SortBy
}
func (s PersonSorter) Len() int { return len(s.people) }
func (s PersonSorter) Swap(i, j int) { s.people[i], s.people[j] = s.people[j], s.people[i] }
func (s PersonSorter) Less(i, j int) bool { return s.less(&s.people[i], &s.people[j]) }
// 使用示例
func main() {
people := []Person{
{"张三", 30},
{"李四", 25},
{"王五", 35},
}
// 按年龄排序
sort.Sort(PersonSorter{
people: people,
less: func(p1, p2 *Person) bool {
return p1.Age < p2.Age
},
})
fmt.Println("按年龄排序:", people)
// 按姓名排序
sort.Sort(PersonSorter{
people: people,
less: func(p1, p2 *Person) bool {
return p1.Name < p2.Name
},
})
fmt.Println("按姓名排序:", people)
}
10. 惰性计算
type LazyEval func() interface{}
func computeExpensiveValue() LazyEval {
computed := false
var result interface{}
return func() interface{} {
if !computed {
fmt.Println("执行昂贵计算...")
// 模拟耗时操作
time.Sleep(1 * time.Second)
result = 42
computed = true
}
return result
}
}
// 使用示例
func main() {
// 创建惰性计算
lazy := computeExpensiveValue()
fmt.Println("惰性计算创建后,尚未执行计算")
// 调用时才执行实际计算
value := lazy()
fmt.Println("第一次获取值:", value)
// 再次调用不会重复计算
value = lazy()
fmt.Println("第二次获取值:", value)
}
函数类型使 Go 拥有了函数式编程的部分能力,同时保持了语言的简洁性和性能,这使得它在构建灵活、可测试和可维护的代码时非常有价值。