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

Golang简化Starlark脚本执行与数据转换的插件库starlet(starlark-go)的使用

✨ Starlet - 增强Starlark的简单方式

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

主要特性

灵活的机器抽象

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

增强的数据转换

Starlet提供了dataconv包,简化了Go和Starlark类型之间的数据交换。它专注于将Go值转换为Starlark等效值,反之亦然,从而更无缝地将Go的丰富数据类型集成到Starlark脚本中。

扩展库和功能

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

安装

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

go get github.com/1set/starlet

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

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

使用示例

以下是一个完整的Go示例,展示如何使用Starlet执行Starlark脚本并进行数据转换:

package main

import (
	"fmt"
	"github.com/1set/starlet"
)

func main() {
	// 定义带有全局变量和模块的机器
	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 Starlark的HTTP客户端和服务器处理程序实现
json 将Starlark值转换为/从JSON字符串的工具
log 在不同严重级别记录消息的功能
path 操作目录和文件路径的函数
random 为各种分布生成随机值的函数
re Starlark的正则表达式函数
runtime 提供Go和应用运行时信息
string 操作字符串的常量和函数

贡献

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

许可证

Starlet根据MIT许可证授权。


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

1 回复

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


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

Starlark是一种类似Python的配置语言,常用于构建系统如Bazel。在Go生态中,starlark-go是官方实现,而starlet是基于它构建的简化插件库,提供了更友好的API和实用功能。

starlet核心功能

starlet主要提供以下便利功能:

  1. 简化脚本执行流程
  2. 自动类型转换(Go ↔ Starlark)
  3. 预置常用模块(math, time, json等)
  4. 错误处理优化

安装

go get github.com/1set/starlet

基础使用示例

package main

import (
	"fmt"
	"github.com/1set/starlet"
)

func main() {
	// 创建执行器
	vm := starlet.New()

	// 执行简单脚本
	result, err := vm.Execute("1 + 2 * 3")
	if err != nil {
		fmt.Printf("执行错误: %v\n", err)
		return
	}
	fmt.Printf("结果: %v\n", result) // 输出: 7
}

变量传递与获取

func main() {
	vm := starlet.New()
	
	// 设置变量到Starlark环境
	err := vm.Set("name", "Alice")
	if err != nil {
		panic(err)
	}
	
	// 执行脚本使用变量
	result, err := vm.Execute("'Hello, ' + name + '!'")
	if err != nil {
		panic(err)
	}
	fmt.Println(result) // 输出: Hello, Alice!
	
	// 从Starlark环境获取变量
	value, err := vm.Get("name")
	if err != nil {
		panic(err)
	}
	fmt.Printf("变量值: %v\n", value) // 输出: Alice
}

复杂数据类型处理

starlet自动处理Go与Starlark类型转换:

func main() {
	vm := starlet.New()
	
	// 传递结构体数据
	data := map[string]interface{}{
		"name":    "Bob",
		"age":     30,
		"hobbies": []string{"reading", "coding"},
	}
	
	err := vm.Set("user", data)
	if err != nil {
		panic(err)
	}
	
	// 执行脚本处理复杂数据
	script := `
user_info = "Name: {}, Age: {}, Hobbies: {}".format(
		user["name"],
		user["age"],
		", ".join(user["hobbies"])
	)
	`
	
	_, err = vm.Execute(script)
	if err != nil {
		panic(err)
	}
	
	// 获取处理结果
	info, err := vm.Get("user_info")
	if err != nil {
		panic(err)
	}
	fmt.Println(info) // 输出: Name: Bob, Age: 30, Hobbies: reading, coding
}

使用预置模块

starlet预加载了多个实用模块:

func main() {
	vm := starlet.New()
	
	// 使用time模块
	script := `
import time
now = time.now()
formatted = time.format(now, "2006-01-02 15:04:05")
	`
	
	_, err := vm.Execute(script)
	if err != nil {
		panic(err)
	}
	
	formatted, err := vm.Get("formatted")
	if err != nil {
		panic(err)
	}
	fmt.Printf("当前时间: %v\n", formatted)
	
	// 使用math模块
	result, err := vm.Execute("math.sqrt(16)")
	if err != nil {
		panic(err)
	}
	fmt.Printf("平方根: %v\n", result) // 输出: 4
}

函数调用

可以在Go中定义函数供Starlark调用:

func main() {
	vm := starlet.New()
	
	// 注册Go函数
	err := vm.Set("greet", func(name string) string {
		return fmt.Sprintf("Hello, %s!", name)
	})
	if err != nil {
		panic(err)
	}
	
	// 调用Go函数
	result, err := vm.Execute("greet('Charlie')")
	if err != nil {
		panic(err)
	}
	fmt.Println(result) // 输出: Hello, Charlie!
}

错误处理

starlet提供了更友好的错误处理:

func main() {
	vm := starlet.New()
	
	// 执行有错误的脚本
	_, err := vm.Execute("1 + 'a'")
	if err != nil {
		if starErr, ok := err.(*starlet.StarletError); ok {
			fmt.Printf("Starlark错误: %v\n", starErr.Message)
			fmt.Printf("位置: %v\n", starErr.Pos)
		} else {
			fmt.Printf("其他错误: %v\n", err)
		}
	}
}

性能考虑

对于需要多次执行的场景,可以预编译脚本:

func main() {
	vm := starlet.New()
	
	// 预编译脚本
	script := `
def calculate(x):
	return x * 2 + 1
	`
	
	_, err := vm.Execute(script)
	if err != nil {
		panic(err)
	}
	
	// 多次调用预编译的函数
	for i := 0; i < 5; i++ {
		result, err := vm.Execute(fmt.Sprintf("calculate(%d)", i))
		if err != nil {
			panic(err)
		}
		fmt.Printf("calculate(%d) = %v\n", i, result)
	}
}

starlet通过简化API和自动类型转换,使得在Go中集成Starlark脚本变得更加容易,特别适合需要灵活配置或规则引擎的场景。

回到顶部