golang简化Starlark脚本执行与数据转换的插件库starlet的使用

✨ Starlet - 超级充电 Starlark,简单至上

Starlet 是另一个针对官方 Starlark in Go 项目的 Go 封装,旨在通过强大的扩展和丰富的封装增强 Starlark 脚本体验,为在 Go 应用中嵌入 Starlark 脚本提供更用户友好且功能强大的接口。

主要特性

灵活的机器抽象

Starlet 引入了执行 Starlark 脚本的简化接口,封装了设置和运行脚本的复杂性。Machine 类型作为 Starlark 运行时环境的全面封装,提供了直观的 API 用于执行 Starlark 脚本、管理全局变量、加载模块、控制脚本执行流程以及处理脚本输出。

增强的数据转换

Starlet 提供了 dataconv 包,简化了 Go 和 Starlark 类型之间的数据交换。与 Starlight 不同,它将 Go 值转换为 Starlark 等效值,反之亦然,实现了 Go 丰富数据类型与 Starlark 脚本更无缝的集成。

扩展的库和功能

Starlet 包含一组自定义模块和库,扩展了 Starlark 语言的功能。这些模块涵盖了文件操作、HTTP 客户端、JSON/CSV 处理等多种用例,使 Starlark 脚本更加强大和多功能。

安装

在项目目录下使用以下 Go 命令安装 Starlet:

go get github.com/1set/starlet

要探索 Starlet CLI 工具的功能,使用以下命令安装:

go install github.com/1set/starlet/cmd/starlet@latest

使用示例

以下是一个快速示例,展示如何在 Go 中使用 Starlet 执行 Starlark 脚本:

import "github.com/1set/starlet"

// 定义带有全局变量和模块的机器
globals := starlet.StringAnyMap{
    "greet": func(name string) string {
        return fmt.Sprintf("Hello, %s!", name)
    },
}
mac := starlet.NewWithNames(globals, []string{"random"}, nil)

// 在机器中运行 Starlark 脚本
script := `
target = random.choice(["World", "Starlark", "Starlet"])
text = greet(target)
print("Starlark:", text)
`
res, err := mac.RunScript([]byte(script), nil)

// 检查错误和结果
if err != nil {
    fmt.Println("Error executing script:", err)
    return
}
fmt.Println("Go:", res["text"].(string))
fmt.Println("Modules:", starlet.GetAllBuiltinModuleNames())

运行此代码可能输出:

Starlark: Hello, Starlet!
Go: Hello, Starlet!
Modules: [atom base64 csv file go_idiomatic hashlib http json log math path random re runtime string struct time]

库列表

Starlet 提供了一系列扩展标准 Starlark 库的库:

包名 描述
atom 整数、浮点和字符串的原子操作
base64 Base64 编码和解码函数
csv 解析和写入 CSV 内容
file 与文件系统交互的函数
goidiomatic Starlark 的 Go 惯用函数和值
hashlib Starlark 的哈希原语
http HTTP 客户端和服务器处理实现
json 将 Starlark 值转换为 JSON 字符串的实用工具
log 在不同严重级别记录消息的功能
path 操作目录和文件路径的函数
random 生成各种分布的随机值的函数
re Starlark 的正则表达式函数
runtime 提供 Go 和应用运行时信息
string 操作字符串的常量和函数

贡献

欢迎对 Starlet 做出贡献。如果您遇到任何问题或有改进建议,请随时提出问题或提交拉取请求。在进行任何重大更改之前,请通过提出问题或认领现有问题来告诉我们,以确保没有重复的工作。

许可证

Starlet 采用 MIT 许可证授权。

致谢

Starlet 受到两个项目的启发:

  1. Starlight:Go 和 Starlark 之间的 Go 封装和数据转换工具。
  2. Starlib:Starlark 的第三方库集合。

我们感谢这些项目的创建者和贡献者的工作。他们的努力为 Starlet 的开发铺平了道路。特别感谢这些项目的作者和贡献者!🎉


更多关于golang简化Starlark脚本执行与数据转换的插件库starlet的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang简化Starlark脚本执行与数据转换的插件库starlet的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用starlet简化Starlark脚本执行与数据转换

starlet是一个优秀的Go库,它简化了在Go应用中执行Starlark脚本以及与Go数据结构相互转换的过程。下面我将详细介绍如何使用这个库。

starlet核心功能

  1. 执行Starlark脚本:在Go环境中运行Starlark脚本
  2. 数据转换:在Go和Starlark数据结构间自动转换
  3. 模块支持:提供标准库模块和自定义模块

基本使用方法

首先安装starlet:

go get github.com/qri-io/starlet

1. 简单脚本执行

package main

import (
	"fmt"
	"github.com/qri-io/starlet"
)

func main() {
	// 创建脚本执行器
	exec := starlet.NewExecutor(nil)

	// 执行简单脚本
	script := `
def greet(name):
    return "Hello, " + name + "!"

result = greet("World")
`
	out, err := exec.Execute(script)
	if err != nil {
		panic(err)
	}

	// 获取结果
	result := out["result"].(string)
	fmt.Println(result) // 输出: Hello, World!
}

2. 数据转换示例

starlet可以自动在Go和Starlark类型间转换:

package main

import (
	"fmt"
	"github.com/qri-io/starlet"
)

func main() {
	exec := starlet.NewExecutor(nil)

	// 输入数据
	input := map[string]interface{}{
		"numbers": []int{1, 2, 3, 4, 5},
		"config": map[string]string{
			"env":  "production",
			"host": "example.com",
		},
	}

	// 处理数据的脚本
	script := `
def process(data):
    total = 0
    for num in data["numbers"]:
        total += num
    
    return {
        "sum": total,
        "env": data["config"]["env"],
        "host": data["config"]["host"],
    }

result = process(input)
`

	// 执行脚本,传入输入数据
	out, err := exec.Execute(script, starlet.StringDict{"input": input})
	if err != nil {
		panic(err)
	}

	// 获取处理后的结果
	result := out["result"].(map[string]interface{})
	fmt.Printf("Sum: %d\n", result["sum"].(int64))
	fmt.Printf("Environment: %s\n", result["env"].(string))
}

3. 使用模块

starlet支持模块化,可以加载标准模块或自定义模块:

package main

import (
	"fmt"
	"github.com/qri-io/starlet"
	"github.com/qri-io/starlib/encoding/json"
)

func main() {
	// 创建执行器并加载json模块
	exec := starlet.NewExecutor(nil)
	exec.AddModule("json", json.Module)

	// 使用json模块处理数据
	script := `
data = {
    "name": "Alice",
    "age": 30,
    "skills": ["Go", "Python", "JavaScript"]
}

json_str = json.encode(data)
parsed = json.decode(json_str)

result = {
    "original": data,
    "json": json_str,
    "parsed": parsed,
}
`

	out, err := exec.Execute(script)
	if err != nil {
		panic(err)
	}

	result := out["result"].(map[string]interface{})
	fmt.Println("JSON string:", result["json"].(string))
}

4. 自定义函数

你可以将Go函数暴露给Starlark脚本使用:

package main

import (
	"fmt"
	"github.com/qri-io/starlet"
	"go.starlark.net/starlark"
)

// 自定义Go函数
func toUpper(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
	var s string
	if err := starlark.UnpackArgs("toUpper", args, kwargs, "s", &s); err != nil {
		return nil, err
	}
	return starlark.String(strings.ToUpper(s)), nil
}

func main() {
	exec := starlet.NewExecutor(nil)
	
	// 添加自定义函数
	exec.AddStringDict("utils", starlet.StringDict{
		"toUpper": starlet.NewBuiltin("toUpper", toUpper),
	})

	script := `
text = "hello starlark"
upper_text = utils.toUpper(text)
result = {
    "original": text,
    "upper": upper_text,
}
`

	out, err := exec.Execute(script)
	if err != nil {
		panic(err)
	}

	result := out["result"].(map[string]interface{})
	fmt.Println("Original:", result["original"].(string))
	fmt.Println("Upper:", result["upper"].(string))
}

高级用法

错误处理

out, err := exec.Execute(script)
if err != nil {
    if evalErr, ok := err.(*starlark.EvalError); ok {
        fmt.Println("Script error:", evalErr.Msg)
        fmt.Println("Call stack:", evalErr.Backtrace())
    } else {
        fmt.Println("Execution error:", err)
    }
    return
}

性能优化

对于频繁执行的脚本,可以预先编译:

// 预编译脚本
compiled, err := exec.Compile(script)
if err != nil {
    panic(err)
}

// 多次执行编译后的脚本
for i := 0; i < 10; i++ {
    out, err := exec.ExecuteCompiled(compiled, starlet.StringDict{"iteration": i})
    if err != nil {
        panic(err)
    }
    fmt.Println(out["result"])
}

总结

starlet提供了以下优势:

  1. 简化了Starlark脚本在Go中的执行
  2. 自动处理Go与Starlark类型转换
  3. 支持模块化扩展
  4. 提供良好的错误处理和性能优化选项

这使得它在配置处理、规则引擎、数据转换等场景中非常有用。

回到顶部