面试题答案
一键面试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
方法时,工作者能停止接收新请求,并等待已处理请求完成,实现优雅退出。