You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go项目中使用Goja执行含其他JS文件引用的JS代码的方法

Goja执行含import的JS代码报错的解决办法

Goja默认不支持ES模块的import语法,也不会自动加载依赖的JS文件,直接用RunCode执行包含import的代码必然报错。以下是几种可行的解决方式:

方法1:手动合并依赖文件(适合简单场景)

如果依赖文件数量不多,可以手动读取所有依赖的JS内容,拼接成完整的JS字符串后再执行。示例代码:

package main

import (
	"os"
	"github.com/dop251/goja"
	"log"
)

func main() {
	// 读取依赖文件
	lodashBytes, err := os.ReadFile("./lodash.js")
	if err != nil {
		log.Fatalf("read lodash.js err: %v", err)
	}
	formulaBytes, err := os.ReadFile("./formula.js")
	if err != nil {
		log.Fatalf("read formula.js err: %v", err)
	}
	// 读取主文件
	calculateBytes, err := os.ReadFile("./calculate.js")
	if err != nil {
		log.Fatalf("read calculate.js err: %v", err)
	}

	// 拼接代码:先注入依赖变量,再执行主逻辑
	fullJS := `
// 注入lodash导出的方法
const { get, cloneDeep } = ` + string(lodashBytes) + `;
// 注入formula导出的函数集合
const functions = ` + string(formulaBytes) + `;
` + string(calculateBytes)

	// 注意:需要修改calculate.js,删除原来的import语句,直接使用上面注入的变量

	vm := goja.New()
	_, err = vm.RunString(fullJS)
	if err != nil {
		log.Fatalf("run code err: %+v", err)
	}
}

方法2:实现Goja的ModuleLoader接口(推荐,支持自动加载)

Goja提供ModuleLoader接口,可自定义模块加载逻辑,让它自动解析import路径并读取对应文件。示例代码:

package main

import (
	"os"
	"path/filepath"
	"github.com/dop251/goja"
	"github.com/dop251/goja/parser"
	"log"
)

type FileModuleLoader struct {
	baseDir string // JS文件所在的基础目录
}

func (l *FileModuleLoader) LoadModule(vm *goja.Runtime, moduleName string) (*goja.Object, error) {
	// 拼接完整文件路径
	filePath := filepath.Join(l.baseDir, moduleName)
	if !filepath.IsAbs(filePath) {
		filePath = filepath.Join(l.baseDir, filePath)
	}
	// 读取文件内容
	code, err := os.ReadFile(filePath)
	if err != nil {
		return nil, err
	}
	// 编译模块代码
	program, err := parser.ParseFile(nil, filePath, code, parser.Mode(0))
	if err != nil {
		return nil, err
	}
	// 运行模块并返回导出对象
	return vm.RunProgram(program)
}

func main() {
	vm := goja.New()
	// 设置自定义模块加载器
	vm.SetModuleLoader(&FileModuleLoader{
		baseDir: "./", // 你的JS文件所在目录
	})

	// 读取主文件
	calculateBytes, err := os.ReadFile("./calculate.js")
	if err != nil {
		log.Fatalf("read calculate.js err: %v", err)
	}

	// 以模块模式解析并运行代码
	program, err := parser.ParseFile(nil, "calculate.js", calculateBytes, parser.Mode(parser.Module))
	if err != nil {
		log.Fatalf("parse code err: %v", err)
	}

	_, err = vm.RunProgram(program)
	if err != nil {
		log.Fatalf("run program err: %+v", err)
	}
}

注意:此方式要求JS代码符合ES模块规范,且使用较新版本的Goja。

方法3:用打包工具合并成单文件

使用webpack、esbuild等工具,将所有依赖的JS文件打包成一个不含import的单文件,再用Goja执行。比如用esbuild的命令:

esbuild calculate.js --bundle --outfile=bundle.js

之后在Go代码中读取bundle.js内容,直接用RunCode执行即可。

内容的提问来源于stack exchange,提问作者wanghao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:43:29