go+lua实现可自定义逻辑websocket服务端

443 阅读1分钟

使用go + lua 做一个webSocket服务端,可以自定义消息处理逻辑 在平时的开发中,前端总会有需要调试webSocket 的场景,后端还没做出来,这时候只能模拟一个webSocket服务端,有个这个,模拟啥都行。

实现步骤

开发中用到了

github.com/gorilla/websocket 
github.com/yuin/gopher-lua

实现这个工具,go 负责 接,发 lua 负责“化”,lua是一门动态语言,牛人用go做了个lua的虚拟机,使得go + lua 的成为了可能,动静结合。

整体消息的处理过程如下

image.png

先写个lua 脚本,比较简单,接收一个参数,并返回这个参数 后缀一个 for lua

-- 实现一个 echo 逻辑
function echoMsg(msg)
    return msg.."-".."for lua"
end

接下来看下怎么在go 中调用lua 脚本,并进行传参

func LuaEcho(msg string) string  {
    // 加载lua 脚本
    codeToShare, _ := CompileLua("data/hello.lua")
    // 创建虚拟机
    a := lua.NewState()
    // 编译脚本
    _=DoCompiledFile(a, codeToShare)
    // 调用lua方法 调用脚本中写的 echoMsg 方法,并传入参数 
    _=a.CallByParam(lua.P{
        Fn:      a.GetGlobal("echoMsg"),
        NRet:    1,
        Protect: false,
    },lua.LString(msg))
    // 获取第一个返回值
    lv:=a.Get(-1)
    if echoMsg,ok:=lv.(lua.LString);ok{
        log.Println(echoMsg)
        return echoMsg.String()
    }
    return "error"
}

然后用go实现一个webSocket,webSocket 监听地址从命令行参数获取

// 定义一个 addr 的命令行参数
var addr = flag.String("addr", "127.0.0.1:1717", "http service address")
​
var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
} // use default optionsfunc main() {
    flag.Parse()
    log.SetFlags(0)
    http.HandleFunc("/", echo)
    log.Fatal(http.ListenAndServe(*addr, nil))
}
// websocket echo 逻辑 
func echo(w http.ResponseWriter, r *http.Request)  {
    c, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Print("upgrade:", err)
        return
    }
    defer c.Close()
    for {
        mt, message, err := c.ReadMessage()
        if err != nil {
            log.Println("read:", err)
            break
        }
        log.Printf("recv: %s", string(message))
        // 调用 lua 方法,并获取返回值
        rsMsg := loadLua.LuaEcho(string(message))
        err = c.WriteMessage(mt, []byte(rsMsg))
        if err != nil {
            log.Println("write:", err)
            break
        }
    }
}
​

到这里代码就完了,比较简单,编译运行下

image-20230117094729163.png