showliuzp 2025-10-21 14:06 采纳率: 84.3%
浏览 2
已结题

golang链表查找封装

 
//聊天数据结构定义
//聊天websocket连接数据结构定义
type chat_websocket_conn struct{
    user_conn       *tools.WebSocketConn    //已建立的客户端连接,lu_guild_account_list表id
    client_id       string                  //生成的唯一id,标识一个客户端
    user_type       int                     //用户类型,1:会员 2:主播
    user_id         int64                   //用户id
    user_nickname   string                  //用户昵称
}
 
 
//链表定义
package tools
 
import (
    "sync"
    "fmt"
    )
 
//并发安全单链表
type SingleNode struct {
    Data interface{}
    Next *SingleNode
}
 
type SingleList struct {
    Mutex *sync.RWMutex //读写锁
 
    Head  *SingleNode   //头节点
    Tail  *SingleNode   //尾节点
 
    Size  uint          //总数
}
 
func NewLinkedList() *SingleList {
    return &SingleList{
        Size:  0,
        Head:  nil,
        Tail:  nil,
        Mutex: new(sync.RWMutex),
    }
}
 
//后插元素
func (List *SingleList) LastAppend(node *SingleNode) bool {
    if node == nil {
        return false
    }
 
    List.Mutex.Lock()
 
    defer List.Mutex.Unlock()
 
    if List.Size == 0 {
        List.Head = node
        List.Tail = node
        List.Size = 1
        return true
    }
 
    tail := List.Tail
 
    tail.Next = node
    List.Tail = node
 
    List.Size += 1
 
    return true
}
 
//删除链表中的指定值节点,通过回调函数实现无侵入删除
func (List *SingleList) DelLinkedNode(f func(data interface{}) bool) bool {
    if List.Size == 0 {
        return false
    }
 
    List.Mutex.Lock()
 
    defer List.Mutex.Unlock()
 
    var prev *SingleNode = nil
    current := List.Head
 
    for current != nil {
        if f(current.Data){
            if prev == nil {
                List.Head = current.Next
            } else {
                prev.Next = current.Next
            }
 
            List.Size--
 
            if List.Size == 0 {
                List.Tail = nil
            }
 
            return true
        }
 
        prev = current
        current = current.Next
    }
 
    prev = nil
 
    return false
}
 
//查找链表中是否有指定值节点,通过回调函数实现无侵入查找
func (List *SingleList) FindLinkedNode(f func(data interface{}) bool) bool {
    if List.Size == 0 {
        return false
    }
 
    List.Mutex.Lock()
 
    defer List.Mutex.Unlock()
 
    current := List.Head
 
    var count uint = 0
    for current != nil {
        if !f(current.Data){
            count++
        }
 
        current = current.Next
    }
 
    if count >= List.Size{
        return false
    }
 
    return true
}

 
//查找每个主播|会员的链表节点是否存在,根据生成的clientid
//作为回调函数传入链表,通过闭包函数实现无侵入校验
func find_linked_node_userid(user_id int64) func(interface{}) bool {
    return func(data interface{}) bool{
        //强制类型转换
        conn, ok := data.(chat_websocket_conn)
        if ok && conn.user_id == user_id {
            return true
        }
 
        return false
    }
}
 
 
//调用:

    item := chat_websocket_conn{
        user_conn       : tools.WebSocketConnMapOnce.ConnMap[client_id],
        client_id       : *client_id,
        user_type       : (*user_info).Flag,
        user_id         : (*user_info).Id,
        user_nickname   : (*user_info).NickName,
    }

    linked_node := tools.SingleNode{Data:item}
    tools.NewLinkedLis.LastAppend(&linked_node)


tools.NewLinkedList().FindLinkedNode(find_linked_node_userid(client_id))
tools.NewLinkedList().FindLinkedNode(find_linked_node_clientid(user_id))
find_linked_node_userid、find_linked_node_clientid为回调的闭包函数,仅仅是 if ok && conn.client_id == *client_id/ if ok && conn.user_id == user_id ,这里不一样,逻辑都是一样的,我想把他们封装成通用的,应该怎么封装?


  • 写回答

3条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-10-21 14:23
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案让您满意,请采纳、点赞、关注,非常感谢!
    .
    每日一句正能量,让它带给您好心情:把生活过得热气腾腾,就是最好的状态。
    .

    根据你的需求,可以将查找函数封装成一个通用的工厂函数,通过参数指定要比较的字段和值。以下是改进方案:

    通用查找函数封装

    // 通用查找条件类型
    type FindCondition struct {
        FieldName string      // 字段名: "user_id" 或 "client_id"
        Value     interface{} // 要比较的值
    }
    
    
    // 通用查找函数生成器
    func CreateFindFunc(condition FindCondition) func(interface{}) bool {
        return func(data interface{}) bool {
            conn, ok := data.(chat_websocket_conn)
            if !ok {
                return false
            }
            
            switch condition.FieldName {
            case "user_id":
                if intValue, ok := condition.Value.(int64); ok {
                    return conn.user_id == intValue
                }
            case "client_id":
                if strValue, ok := condition.Value.(string); ok {
                    return conn.client_id == strValue
                }
            default:
                return false
            }
            
            return false
        }
    }
    

    使用示例

    // 查找指定用户ID
    findFunc1 := CreateFindFunc(FindCondition{
        FieldName: "user_id",
        Value:     int64(12345),
    })
    found1 := tools.NewLinkedList().FindLinkedNode(findFunc1)
    
    
    // 查找指定客户端ID
    findFunc2 := CreateFindFunc(FindCondition{
        FieldName: "client_id", 
        Value:     "client_abc123",
    })
    found2 := tools.NewLinkedList().FindLinkedNode(findFunc2)
    

    更灵活的封装方案

    如果你需要支持更多字段,可以使用反射来实现更通用的方案:

    import "reflect"
    
    
    // 使用反射的通用查找函数
    func CreateFindFuncByReflect(fieldName string, expectedValue interface{}) func(interface{}) bool {
        return func(data interface{}) bool {
            conn, ok := data.(chat_websocket_conn)
            if !ok {
                return false
            }
            
            // 使用反射获取字段值
            v := reflect.ValueOf(conn)
            field := v.FieldByName(fieldName)
            
            if !field.IsValid() {
                return false
            }
            
            // 比较字段值
            return reflect.DeepEqual(field.Interface(), expectedValue)
        }
    }
    

    使用反射版本的示例

    // 查找用户ID
    findFunc1 := CreateFindFuncByReflect("user_id", int64(12345))
    found1 := tools.NewLinkedList().FindLinkedNode(findFunc1)
    
    
    // 查找客户端ID  
    findFunc2 := CreateFindFuncByReflect("client_id", "client_abc123")
    found2 := tools.NewLinkedList().FindLinkedNode(findFunc2)
    
    
    // 查找用户类型
    findFunc3 := CreateFindFuncByReflect("user_type", 1)
    found3 := tools.NewLinkedList().FindLinkedNode(findFunc3)
    

    建议

    1. 推荐使用第一种方案(基于switch-case),性能更好,类型安全
    2. 如果字段数量固定且不多,第一种方案更合适
    3. 如果需要动态支持任意字段,可以使用反射方案
    4. 可以在FindCondition中添加比较操作符支持(等于、不等于等)来增强灵活性

    这样封装后,你只需要一个函数就能处理所有字段的查找需求,代码更加简洁和可维护。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 10月29日
  • 已采纳回答 10月21日
  • 创建了问题 10月21日