From ae43530608802224facb189ef446835ba16c42e1 Mon Sep 17 00:00:00 2001 From: kingecg Date: Fri, 19 Sep 2025 21:35:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0Anko=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E8=AF=AD=E6=B3=95=E6=8C=87=E5=8D=97=E5=8F=8A=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=8B=A6=E6=88=AA=E5=99=A8=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/anko_syntax_guide.md | 110 +++++++++++++++++++++++++++++++++++++ interceptor/interceptor.go | 23 ++++++++ 2 files changed, 133 insertions(+) create mode 100644 doc/anko_syntax_guide.md diff --git a/doc/anko_syntax_guide.md b/doc/anko_syntax_guide.md new file mode 100644 index 0000000..6e08ad0 --- /dev/null +++ b/doc/anko_syntax_guide.md @@ -0,0 +1,110 @@ +# go-lang-anko 脚本语法指南 + +## 简介 +`anko` 是一个用 Go 编写的轻量级脚本引擎,支持动态执行 Go 风格的脚本代码。它适用于需要嵌入脚本功能的 Go 应用程序。 + +## 基本语法 + +### 变量声明与赋值 +```go +// 声明变量并赋值 +x = 42 +name = "anko" + +// 多变量赋值 +a, b = 1, 2 +``` + +### 控制结构 +#### if 语句 +```go +if x > 0 { + println("x is positive") +} else { + println("x is non-positive") +} +``` + +#### for 循环 +```go +// 类似 Go 的 for 循环 +for i = 0; i < 10; i++ { + println(i) +} + +// 类似 while 的循环 +for x < 100 { + x *= 2 +} +``` + +#### switch 语句 +```go +switch x { +case 1: + println("one") +case 2: + println("two") +default: + println("unknown") +} +``` + +### 函数定义与调用 +```go +// 定义函数 +func add(a, b) { + return a + b +} + +// 调用函数 +result = add(3, 4) +``` + +### 内置函数和标准库 +`anko` 支持部分 Go 标准库函数,例如: +```go +// 字符串操作 +s = "hello" +println(len(s)) // 输出 5 + +// 数学函数 +println(math.Pi) +``` + +### 错误处理 +```go +// 使用 try-catch 捕获错误 +try { + x = 1 / 0 +} catch(err) { + println("Error:", err) +} +``` + +## 示例代码 + +### 计算斐波那契数列 +```go +func fib(n) { + if n <= 1 { + return n + } + return fib(n-1) + fib(n-2) +} + +println(fib(10)) // 输出 55 +``` + +### 文件操作 +```go +// 读取文件内容 +content = file.Read("example.txt") +println(content) +``` + +## 注意事项 +1. **性能**:`anko` 是解释执行的,性能不如原生 Go 代码。 +2. **安全性**:避免执行不可信的脚本代码。 +3. **限制**:不支持 Go 的所有特性(如指针、接口等)。 +4. **调试**:使用 `println` 或 `try-catch` 进行简单调试。 \ No newline at end of file diff --git a/interceptor/interceptor.go b/interceptor/interceptor.go index 8510455..2c823f9 100644 --- a/interceptor/interceptor.go +++ b/interceptor/interceptor.go @@ -35,8 +35,19 @@ func NewAnkointerceptor(ankoEnv *env.Env) *Ankointerceptor { return a } +// Exec executes the specified script within the Anko environment. +// It sets up the environment with necessary variables and methods, +// reads the script file, and executes it, returning the result or an error. +// +// Parameters: +// - script: Path to the script file to be executed. +// +// Returns: +// - interface{}: The result of the script execution. +// - error: An error if the script file cannot be read or execution fails. func (a *Ankointerceptor) Exec(script string) (interface{}, error) { e := a.ankoEnv.Copy() + // Configure the Anko environment with required variables and methods e.Define("Require", a.genRequireMethod(script)) e.Define("__filename", script) e.Define("__dirname", filepath.Dir(script)) @@ -45,6 +56,7 @@ func (a *Ankointerceptor) Exec(script string) (interface{}, error) { return nil, frr } scriptcode := string(scriptbytes) + // Execute the script code in the prepared environment result, err := vm.Execute(e, nil, scriptcode) if err != nil { fmt.Println(err) @@ -53,17 +65,28 @@ func (a *Ankointerceptor) Exec(script string) (interface{}, error) { return result, nil } +// genRequireMethod 创建模块解析闭包函数 +// 该函数用于处理模块路径解析和缓存机制: +// 1. 优先从importMap缓存中查找已加载模块 +// 2. 对相对路径自动转换为基于basePath的绝对路径 +// 3. 执行模块加载后自动缓存结果 +// 参数: +// basePath - 模块基础路径,用于解析相对路径 +// 返回: +// 闭包函数,接收模块路径s,返回解析后的模块对象 func (a *Ankointerceptor) genRequireMethod(basePath string) interface{} { return func(s string) interface{} { if r, ok := a.importMap[s]; ok { return r } + // 将相对路径转换为基于basePath的绝对路径 if !filepath.IsAbs(s) { s = filepath.Join(filepath.Dir(basePath), s) } if _, ok := a.importMap[s]; ok { return a.importMap[s] } + // 执行模块加载并将结果缓存 result, err := a.Exec(s) if err != nil { panic(err)