天天看點

go otto js插件化

  這幾天發現了一個特别有趣的東西,隻要照着規定好的插件模闆寫,不懂go文法的人也可以互動go代碼,大大提高了go代碼的可擴充性,易用性。

  1. 範例代碼

    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'
}
           
  1. 測試,運作

    main.go

    ,通路

    http://localhost:8080

go otto js插件化

繼續閱讀