這幾天發現了一個特别有趣的東西,隻要照着規定好的插件模闆寫,不懂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