Loading... > [Yaegi 是另一个优雅的 Go 解释器](https://github.com/traefik/yaegi) 优不优雅不知道,至少作者是这样介绍的,毕竟go讲究的就是一个优雅  Yaegi 是另一个优雅的 Go 解释器。它在 Go 运行时之上为嵌入式解释器或交互式 shell 中的可执行 Go 脚本和插件提供支持。 ## 特征 * 完整支持[Go规范](https://golang.org/ref/spec) * 用纯 Go 编写,仅使用标准库 * 简单的解释器 API: `New()`, `Eval()`,`Use()` * 无处不在 * 可从脚本访问的所有 Go 和运行时资源(带控件) * 安全性:默认情况下既不使用也不导出`unsafe`包`syscall` * 支持 Go 1.18 和 Go 1.19(最新的 2 个主要版本) ## 安装 ### 去包 ```go notranslate position-relative overflow-auto import "github.com/traefik/yaegi/interp" ``` ### 命令行可执行文件 ```shell notranslate position-relative overflow-auto go get -u github.com/traefik/yaegi/cmd/yaegi ``` 请注意,您可以使用[rlwrap](https://github.com/hanslub42/rlwrap)(使用您最喜欢的包管理器安装),并在您的 中为`yaegi`命令添加别名,以获得历史记录和命令行版本。`alias yaegi='rlwrap yaegi'``~/.bashrc` ### CI整合 ```shell notranslate position-relative overflow-auto curl -sfL https://raw.githubusercontent.com/traefik/yaegi/master/install.sh | bash -s -- -b $GOPATH/bin v0.9.0 ``` ## 用法 ### 作为嵌入式解释器 创建一个解释器`New()`,运行 Go 代码`Eval()`: ```go notranslate position-relative overflow-auto package main import ( "github.com/traefik/yaegi/interp" "github.com/traefik/yaegi/stdlib" ) func main() { i := interp.New(interp.Options{}) i.Use(stdlib.Symbols) _, err := i.Eval(`import "fmt"`) if err != nil { panic(err) } _, err = i.Eval(`fmt.Println("Hello Yaegi")`) if err != nil { panic(err) } } ``` [去游乐场](https://play.golang.org/p/2n-EpZbMYI9) ### 作为动态扩展框架 下面的程序是提前编译的,除了`bar()`它是解释的,步骤如下: 1. 在解释器的上下文中使用`i.Eval(src)`评估脚本 2. 使用 of`v, err := i.Eval("foo.Bar")`从解释器上下文中获取符号,作为`reflect.Value` 3. 应用`Interface()`方法和类型断言以转换`v`为`bar`,就好像它已被编译一样 ```go notranslate position-relative overflow-auto package main import "github.com/traefik/yaegi/interp" const src = `package foo func Bar(s string) string { return s + "-Foo" }` func main() { i := interp.New(interp.Options{}) _, err := i.Eval(src) if err != nil { panic(err) } v, err := i.Eval("foo.Bar") if err != nil { panic(err) } bar := v.Interface().(func(string) string) r := bar("Kung") println(r) } ``` [去游乐场](https://play.golang.org/p/WvwH4JqrU-p) ### 作为命令行解释器 Yaegi 命令可以运行交互式 Read-Eval-Print-Loop: ``` $ yaegi > 1 + 2 3 > import "fmt" > fmt.Println("Hello World") Hello World > ``` 请注意,在交互模式下,所有 stdlib 包都是预先导入的,您可以直接使用它们: ``` $ yaegi > reflect.TypeOf(time.Date) : func(int, time.Month, int, int, int, int, int, *time.Location) time.Time > ``` 或者解释 Go 的包、目录或文件,包括它自己: ``` $ yaegi -syscall -unsafe -unrestricted github.com/traefik/yaegi/cmd/yaegi > ``` 或者对于 shebang 行中的 Go 脚本: ``` $ cat /tmp/test #!/usr/bin/env yaegi package main import "fmt" func main() { fmt.Println("test") } $ ls -la /tmp/test -rwxr-xr-x 1 dow184 dow184 93 Jan 6 13:38 /tmp/test $ /tmp/test test ``` ## 文档 通常可以在 godoc.org 找到有关 Yaegi 命令和库的[文档](https://pkg.go.dev/github.com/traefik/yaegi)。 ## 限制 除了应该在短期内修复的已知[错误](https://github.com/traefik/yaegi/issues?q=is%3Aissue+is%3Aopen+label%3Abug)之外,还有一些限制不会很快解决: * `.s`不支持程序集文件 ( )。 * 不支持调用 C 代码(没有虚拟“C”包)。 * 预编译代码中要使用的接口不能动态添加,因为需要预编译接口包装器。 * 使用 %T表示类型`reflect`和打印值可能会在编译模式和解释模式之间给出不同的结果。 * 解释计算密集型代码可能比在编译模式下慢得多。 最后修改:2022 年 11 月 19 日 © 允许规范转载 打赏 赞赏作者 微信 赞 3 如果觉得我的文章对你有用,请随意赞赏