go otto js插件化

    科技2022-08-14  102

      这几天发现了一个特别有趣的东西,只要照着规定好的插件模板写,不懂go语法的人也可以交互go代码,大大提高了go代码的可扩展性,易用性。

    范例代码 main.go package main import ( "fmt" "github.com/gin-gonic/gin" "log" ) func main(){ //加载文件夹下所有插件 plugins:=loadPlugins("./jsfilters") r:=gin.New() r.Use(func(context *gin.Context) { exchange:=NewExchange(context.Request) //遍历调用所有插件主函数 for _,p:=range plugins{ p.Filter(exchange) } context.Next() }) r.Handle("GET","/", func(context *gin.Context) { //打印header头 fmt.Println(context.Request.Header.Get("Name")) fmt.Println(context.Request.Header.Get("Age")) context.JSON(200,gin.H{"result":"ok"}) }) err := r.Run(":8080") if err!=nil{ log.Panic(err) } }

    helper.go(交互逻辑代码)

    package main import ( "github.com/robertkrimen/otto" "io/ioutil" "log" "net/http" "path" ) func readFile(file string) string { b,err:=ioutil.ReadFile(file) if err!=nil{ return "" } return string(b) } type This struct { } type Exchange struct { Request *http.Request } func NewExchange(request *http.Request) *Exchange { return &Exchange{Request:request} } type FilterPlugin struct { Name string Main otto.Value } //调用插件对象里的mian方法 func(self *FilterPlugin) Filter(exchange *Exchange){ this,_:=otto.ToValue(nil) _,err:=self.Main.Call(this,exchange) //调用 闭包 ,传递上下文参数 if err!=nil{ log.Println(err) } } func loadPlugin(js *otto.Otto) *FilterPlugin { //获取插件名称 filter_name,err:=js.Call("name",nil) if err!=nil{ log.Println(err) return nil } //获取插件主函数 filter_main,err:=js.Call("main",nil) if err!=nil || !filter_main.IsFunction(){ log.Println(err) return nil } //返回插件对象 return &FilterPlugin{Name:filter_name.String(),Main:filter_main} } //加载文件夹下所有插件 func loadPlugins(dirname string) []*FilterPlugin { //插件对象切片 ret:=make([]*FilterPlugin,0) //读取文件夹 fileInfos, _ := ioutil.ReadDir(dirname) //遍历文件 for _, file := range fileInfos { if !file.IsDir() && path.Ext(file.Name())==".js"{ //如果是JS文件 js:=otto.New() //运行 _,err:=js.Run(readFile(dirname+"/"+file.Name())) if err!=nil{ log.Println(err) continue } if p:=loadPlugin(js);p!=nil{ //获取到插件对象,则追加到数组 ret=append(ret,p) } } } return ret }

    JS模板1

    function main() { return function (exchange) { //设置header头 exchange.Request.Header.Set("Name","shenyi") } } //插件名 function name() { return 'Test' }

    JS模板2

    function main() { return function (exchange) { //设置header头 exchange.Request.Header.Set("Age",19) } } //插件名 function name() { return 'Abc' } 测试,运行main.go,访问http://localhost:8080

    Processed: 0.013, SQL: 8