概述
Tengo is a small, dynamic, fast, secure script language for Go.
作为一款编译和运行都在go编写的本地堆栈vm上完成的脚本语言,tengo对比其他脚本语言具有更快速和更安全的特点。本文主要介绍如何在tengo中导入并使用自定义module。
1.定义一个module
用户自定义module,一般需要实现Importable接口。
// Importable interface represents importable module instance.
type Importable interface {
// Import should return either an Object or module source code ([]byte).
Import(moduleName string) (interface{}, error)
}
//我们的实现如下:
// MyModule is an importable module that's written in Go.
type MyModule struct {
Attrs map[string]tengo.Object
}
// Import returns an immutable map for the module.
func (m *MyModule) Import(moduleName string) (interface{}, error) {
return m.AsImmutableMap(moduleName), nil
}
// AsImmutableMap converts builtin module into an immutable map.
func (m *MyModule) AsImmutableMap(moduleName string) *tengo.ImmutableMap {
attrs := make(map[string]tengo.Object, len(m.Attrs))
for k, v := range m.Attrs {
attrs[k] = v.Copy()
}
attrs["__module_name__"] = &tengo.String{Value: moduleName}
return &tengo.ImmutableMap{Value: attrs}
}
然后,我们需要用我们实现的Importable接口类,即MyModule,声明一个map[string]tengo.Object结构。
package tengo_module
import (
"github.com/d5/tengo/v2"
)
//我们的库里新增了一个用户自定义函数,名字为hello。
var JoyboiiModule = &MyModule {
Attrs: map[string]tengo.Object{
"hello": &tengo.UserFunction{Name: "hello", Value: hello},
},
}
//完成参数校验、错误处理等工作,最终完成我们需要的工作。
func hello(args ...tengo.Object) (ret tengo.Object, err error) {
if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments
} else if f1, ok := tengo.ToString(args[0]); !ok {
return nil, tengo.ErrInvalidArgumentType{
Name: "one",
Expected: "string",
Found: args[0].TypeName(),
}
} else {
return &tengo.String{Value:"hello, " + f1}, nil
}
}
2.验证效果
package main
import (
"draft/tengo_module"
"fmt"
"github.com/d5/tengo/v2"
"github.com/d5/tengo/v2/stdlib"
)
var src = `
fmt := import("fmt")
joyboii := import("joyboii")
res := joyboii.hello("joyboii")
fmt.println("tengo_module res: ", res)
`
func main() {
script := tengo.NewScript([]byte(src))
//拓展我们自己的module
modules := stdlib.GetModuleMap(stdlib.AllModuleNames()...)
modules.Add("joyboii",tengo_module.JoyboiiModule)
script.SetImports(modules)
//编译并运行
compiled, err := script.Compile()
if err != nil {
fmt.Println(err)
return
}
err = compiled.Run()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("go res:", compiled.Get("res"))
}
最终输出结果为:
tengo_module res: hello, joyboii
go res: hello, joyboii
官方资料
- Tengo github : github.com/d5/tengo
- Tengo Playgroud: tengolang.com/