面试题答案
一键面试数据结构设计
- 消息结构体:定义一个通用的消息结构体,包含消息类型标识和实际数据,使用空接口来承载不同类型的数据。
type Message struct {
Type string
Data interface{}
}
- 处理器映射:使用一个map来存储不同类型消息对应的处理器函数。
type HandlerMap map[string]func(interface{})
处理逻辑
- 注册处理器:提供一个函数来注册不同类型消息的处理器。
func (hm HandlerMap) RegisterHandler(messageType string, handler func(interface{})) {
hm[messageType] = handler
}
- 分发消息:实现一个消息分发函数,根据消息类型调用相应的处理器。
func (hm HandlerMap) DispatchMessage(msg Message) {
if handler, ok := hm[msg.Type]; ok {
handler(msg.Data)
} else {
// 处理未注册类型的消息,例如记录日志
log.Printf("Unregistered message type: %s", msg.Type)
}
}
优化策略
- 减少类型断言次数:在处理器注册时,尽量在编译期确定类型,而不是在运行时频繁进行类型断言。例如,可以为不同类型的数据定义特定的处理器接口,在注册时进行类型检查。
- 使用类型开关预编译:在处理器函数内部,如果需要进行类型断言,可以使用
switch
语句结合type
关键字,Go编译器会对这种类型开关进行优化,提高性能。
func handler(data interface{}) {
switch v := data.(type) {
case string:
// 处理string类型数据
case int:
// 处理int类型数据
}
}
并发控制手段
- 互斥锁:为
HandlerMap
添加读写锁,防止在注册处理器和分发消息时出现竞态条件。
type SafeHandlerMap struct {
mu sync.RWMutex
inner HandlerMap
}
func (shm *SafeHandlerMap) RegisterHandler(messageType string, handler func(interface{})) {
shm.mu.Lock()
defer shm.mu.Unlock()
shm.inner.RegisterHandler(messageType, handler)
}
func (shm *SafeHandlerMap) DispatchMessage(msg Message) {
shm.mu.RLock()
defer shm.mu.RUnlock()
shm.inner.DispatchMessage(msg)
}
- 使用sync.Map:Go的
sync.Map
是一个线程安全的map,在高并发场景下可以直接使用它来存储处理器映射,避免手动加锁。
type SyncHandlerMap struct {
inner sync.Map
}
func (shm *SyncHandlerMap) RegisterHandler(messageType string, handler func(interface{})) {
shm.inner.Store(messageType, handler)
}
func (shm *SyncHandlerMap) DispatchMessage(msg Message) {
if handler, ok := shm.inner.Load(msg.Type); ok {
h := handler.(func(interface{}))
h(msg.Data)
} else {
// 处理未注册类型的消息,例如记录日志
log.Printf("Unregistered message type: %s", msg.Type)
}
}
- 消息队列:引入消息队列,如
channel
,将消息先发送到队列中,然后由专门的协程从队列中取出消息进行分发处理,避免多个协程同时访问HandlerMap
导致的竞态条件。
func messageDispatcher(hm HandlerMap, msgChan <-chan Message) {
for msg := range msgChan {
hm.DispatchMessage(msg)
}
}
在使用时,创建一个消息队列,并启动消息分发协程。
msgChan := make(chan Message)
go messageDispatcher(hm, msgChan)
// 发送消息到队列
msgChan <- Message{Type: "type1", Data: "data1"}