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

如何使用Golang结合V8Go调用JavaScript匿名函数?

Golang结合V8Go调用JSON-Mask JS文件返回null的修正方案

问题背景

现有一个实现JSON字段掩码功能的JavaScript文件,Java代码可正常调用其中的匿名函数完成掩码处理,但改用Golang + V8Go库实现时,当前代码调用后返回null且无法定位问题,需修正实现逻辑。

Java参考实现

public class JavaScriptEngine {

    private ScriptObjectMirror mirror;
    private Object eval;

    public JavaScriptEngine() throws IOException, ScriptException {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        /**
         * Use the line below to load the file directly from a CDN, this is recommended to get new versions automatically
         * Object eval = engine.eval("load('https://cdn.com/json-mask.js')");
         */
        String absolutePath = new File("src/main/resources/js-code/json-mask.js").getAbsolutePath();
        Object eval = engine.eval(Files.newBufferedReader(Paths.get(absolutePath), StandardCharsets.UTF_8));
        this.mirror = ((ScriptObjectMirror) ((ScriptObjectMirror) eval).get("default"));
        this.eval = eval;
    }

    public String call(String field, String type) {
        String json = "{\"value\": \"" + field + "\" }";
        String setting = "[{\"type\": \""+ type.toUpperCase()+ "\", \"path\": \"$.value\"}]";
        Object aDefault = mirror.call(eval, json, setting);
        Object read = JsonPath.parse(aDefault.toString()).read("$.value");

        return read == null ? null : read.toString();
    }

}

当前存在问题的Go实现

package main

import (
    "encoding/json"
    "fmt"
    "os"
    v8 "rogchap.com/v8go"
)

func main() {
    fmt.Println("test")
    content, err := os.ReadFile("json-mask.js")
    fmt.Println(err)

    ctx := v8.NewContext()
    result, errorJS := ctx.RunScript(string(content), "file.js")
    
    fmt.Println(result)
    fmt.Println(errorJS)

    // the val returns null, I think I'm calling it wrong
    val, _ := ctx.RunScript("result", "value.js")

    fmt.Printf("addition result: %s", val)
}

修正后的Go实现方案

问题分析

  1. 原代码未将JS脚本的导出对象挂载到全局上下文,直接引用result变量会返回null
  2. 未正确提取JS模块中的default函数(对应Java中的mirror对象)
  3. 缺少函数调用的参数构造与执行逻辑
  4. 错误处理不完善,无法定位中间环节的问题

修正代码

package main

import (
	"encoding/json"
	"fmt"
	"os"
	v8 "rogchap.com/v8go"
)

func main() {
	fmt.Println("test")
	// 读取JS文件
	content, err := os.ReadFile("json-mask.js")
	if err != nil {
		fmt.Printf("读取JS文件失败: %v\n", err)
		return
	}

	// 创建V8上下文
	ctx := v8.NewContext()
	// 运行JS脚本,获取模块导出对象
	exportObj, err := ctx.RunScript(string(content), "json-mask.js")
	if err != nil {
		fmt.Printf("运行JS脚本失败: %v\n", err)
		return
	}
	fmt.Println("JS脚本导出对象:", exportObj)

	// 从导出对象中获取default函数
	defaultFuncVal, err := exportObj.AsObject().Get("default")
	if err != nil {
		fmt.Printf("获取default函数失败: %v\n", err)
		return
	}
	if !defaultFuncVal.IsFunction() {
		fmt.Println("导出的default不是函数类型")
		return
	}
	defaultFunc := defaultFuncVal.AsFunction()

	// 构造测试参数(模拟Java call方法的输入)
	testField := "敏感信息123456"
	testType := "MASK"
	jsonParam := fmt.Sprintf(`{"value": "%s"}`, testField)
	settingParam := fmt.Sprintf(`[{"type": "%s", "path": "$.value"}]`, testType)

	// 将参数转换为V8可识别的值
	jsonV8Val, err := v8.NewValue(ctx, jsonParam)
	if err != nil {
		fmt.Printf("构造JSON参数失败: %v\n", err)
		return
	}
	settingV8Val, err := v8.NewValue(ctx, settingParam)
	if err != nil {
		fmt.Printf("构造配置参数失败: %v\n", err)
		return
	}

	// 调用default函数,第一个参数为this对象(对应Java中的eval)
	resultV8Val, err := defaultFunc.Call(exportObj, jsonV8Val, settingV8Val)
	if err != nil {
		fmt.Printf("调用掩码函数失败: %v\n", err)
		return
	}

	// 解析返回结果,提取value字段
	resultStr := resultV8Val.String()
	var resultMap map[string]interface{}
	if err := json.Unmarshal([]byte(resultStr), &resultMap); err != nil {
		fmt.Printf("解析结果JSON失败: %v\n", err)
		return
	}

	maskedValue := resultMap["value"]
	fmt.Printf("原始值: %s\n处理后的值: %v\n", testField, maskedValue)
}

关键修正点

  • 完善错误处理:每一步操作都检查错误,便于快速定位问题
  • 正确提取导出函数:从JS脚本运行结果中获取default函数,确保调用的是正确的处理逻辑
  • 参数转换与传递:将Go字符串参数转为V8可识别的Value类型,并正确传入函数
  • 模拟Java的调用逻辑:函数调用时传入this对象(对应Java中的eval),保证JS函数内部上下文正确
  • 结果解析:将V8返回的结果转为字符串后,用Go标准库解析JSON并提取目标字段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:07:54