MST

星途 面试题库

面试题:Go语言接口声明在并发场景下的最佳实践

假设有一个服务,需要处理多个并发的请求,请求的处理逻辑各不相同,但都可以抽象为一个接口`RequestHandler`,包含`Handle`方法。请设计一个高效的并发处理模型,利用`RequestHandler`接口,处理这些并发请求。在代码中要考虑资源的合理利用、错误处理以及优雅的退出机制。说明你这样设计接口声明及并发处理方式的理由和优势。
42.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

1. 接口声明

// RequestHandler 定义请求处理接口
type RequestHandler interface {
    Handle() error
}

理由:将不同请求处理逻辑抽象为统一接口,使得代码具有高度的可扩展性。不同类型的请求处理可以实现该接口,遵循面向接口编程原则,降低代码耦合度。

2. 并发处理方式

package main

import (
    "context"
    "fmt"
    "sync"
)

// RequestHandler 定义请求处理接口
type RequestHandler interface {
    Handle() error
}

// Worker 工作者结构体,用于处理请求
type Worker struct {
    ctx    context.Context
    cancel context.CancelFunc
    wg     sync.WaitGroup
}

// NewWorker 创建一个新的工作者
func NewWorker() *Worker {
    ctx, cancel := context.WithCancel(context.Background())
    return &Worker{
        ctx:    ctx,
        cancel: cancel,
    }
}

// Start 启动工作者,处理请求
func (w *Worker) Start(requests <-chan RequestHandler) {
    for {
        select {
        case req, ok := <-requests:
            if!ok {
                return
            }
            w.wg.Add(1)
            go func(r RequestHandler) {
                defer w.wg.Done()
                err := r.Handle()
                if err != nil {
                    fmt.Printf("处理请求出错: %v\n", err)
                }
            }(req)
        case <-w.ctx.Done():
            return
        }
    }
}

// Stop 停止工作者
func (w *Worker) Stop() {
    w.cancel()
    w.wg.Wait()
}

使用示例

func main() {
    // 创建工作者
    worker := NewWorker()

    // 创建请求通道
    requests := make(chan RequestHandler)

    // 模拟不同的请求处理实现
    type Request1 struct{}
    func (r *Request1) Handle() error {
        fmt.Println("处理请求1")
        return nil
    }

    type Request2 struct{}
    func (r *Request2) Handle() error {
        fmt.Println("处理请求2")
        return nil
    }

    // 启动工作者
    go worker.Start(requests)

    // 发送请求
    requests <- &Request1{}
    requests <- &Request2{}

    // 关闭请求通道
    close(requests)

    // 停止工作者
    worker.Stop()
}

理由和优势

  • 资源合理利用:使用 goroutine 进行并发处理,goroutine 是轻量级线程,在处理大量并发请求时,资源消耗小。通过 context 控制 goroutine 的生命周期,避免资源泄露。
  • 错误处理:在每个请求处理的 goroutine 中捕获错误并进行处理,确保错误不会导致程序崩溃,提高程序的稳定性。
  • 优雅退出机制:利用 context 的取消功能,当调用 Stop 方法时,工作者能停止接收新请求,并等待已处理请求完成,实现优雅退出。