介绍

Energy Go中定义的变量、结构和函数绑定,在JS中使用。

在Energy中不只可以调用 JS 和 事件机制,也可以通过Go绑定在Go中定义的一些变量函数在JS中调用,在使用的时候就如同在JS调用本身定义的函数一样方便。

运行此示例,需要安装好Go和Energy开发环境:教程一 环境安装

此示例中采用了内置http服务访问内嵌资源:


使用方式

在Go中绑定使用cef.VariableBind.VariableCreateCallback变量创建初始化函数绑定,

支持类型,目前只支持 String, Integer, Boollean, Double(float64), null, undefiend, function
不支持类型 Object, Array

绑定的变量区分为通用类型和结构类型,每个类型都有自己的根对象,在window下为

结构类型: window.goobj
通用类型: window.gocobj
在应用初始化时通过ApplicationConfig对象的SetCommonRootName和SetObjectRootName设置根对象名称

字段取赋值,函数调用

在html中取值、赋值、函数调用

通用类型和结构类型取赋值方式一样,直接通过变量名

字段取值 var demoVar = goobj.demo

字段赋值 goobj.demo='新值'

函数调用 goobj.funcName(xxx,xxx)

通用类型

在绑定变量初始化函数中使用bind.NewXXXX(“name”,[初始值])
通用类型变量可任意更改变量值的类型,在GO中使用时需要类型判断,否则取值失败。
变量值存放在主进程(browser)中,与渲染进程共享。
在Go和Web中共享这些变量可直接修改

结构类型

在绑定变量初始化函数中使用bind.NewObjects(…array)进行结构类型绑定
在Go中定义的struts类型, 该类型变量类型不可更改
变量值存放在主进程(browser)中,与渲染进程共享。
在Go和Web中共享这些变量可直接修改
结构内定义的字段为绑定的字段,首字母需大写,否则绑定不成功。

函数类型

结构类型和通用类型都可定义函数,函数名需首字母大写
入参最多9个,可带有1个返回值

Go代码示例

示例中,在cef.VariableBind.VariableCreateCallback变量绑定函数中对通用类型变量和结构类型进行了绑定

通用类型,使用bind.NewXXX的方式

结构类型,使用bind.NewObjects的方式

main.go

package main

import (
	"embed"
	"fmt"
	"github.com/energye/energy/cef"
	"github.com/energye/energy/common/assetserve"
	"github.com/energye/energy/example/browser-go-bind-js-var/src"
)

//go:embed resources
var resources embed.FS

func main() {
	//全局初始化 每个应用都必须调用的
	cef.GlobalCEFInit(nil, &resources)
	//创建应用
	cefApp := cef.NewApplication(nil)
	//指定一个URL地址,或本地html文件目录
	cef.BrowserWindow.Config.DefaultUrl = "http://localhost:22022/go-bind-js-var.html"
	cef.BrowserWindow.Config.Title = "Energy - execute-javascript"
	cef.BrowserWindow.Config.Icon = "resources/icon.ico"
	//内置http服务链接安全配置
	cef.SetBrowserProcessStartAfterCallback(func(b bool) {
		fmt.Println("主进程启动 创建一个内置http服务")
		//通过内置http服务加载资源
		server := assetserve.NewAssetsHttpServer()
		server.PORT = 22022
		server.AssetsFSName = "resources" //必须设置目录名
		server.Assets = &resources
		go server.StartHttpServer()
	})
	//变量创建回调-这个函数在主进程(browser)和子进程(render)中执行
	//变量的值绑定到主进程
	cef.VariableBind.VariableCreateCallback(func(browser *cef.ICefBrowser, frame *cef.ICefFrame, bind cef.IProvisionalBindStorage) {
		//初始化要绑定的变量
		//结构类型
		src.JSStructVarDemo = &src.StructVarDemo{}
		src.JSStructVarDemo.StringField = "初始的字符串值"
		bind.NewObjects(src.JSStructVarDemo)
		//通用类型
		src.JSString = bind.NewString("JSString", "初始的字符串值")
		src.JSInt = bind.NewInteger("JSInt", 0)
		src.JSBool = bind.NewBoolean("JSBool", false)
		src.JSDouble = bind.NewDouble("JSDouble", 0.0)
		_ = bind.NewFunction("JSFunc", src.JSFunc)
	})
	//运行应用
	cef.Run(cefApp)
}

src/common-var.go

定义了通用类型变量

package src

import (
	"fmt"
	"github.com/energye/energy/cef"
)

var (
	JSString *cef.JSString
	JSInt    *cef.JSInteger
	JSBool   *cef.JSBoolean
	JSDouble *cef.JSDouble
)

func JSFunc(p1 string) string {
	fmt.Println("Go中执行JSFunc 参数:", p1)
	var ret string
	//类型判断
	if JSString.IsString() {
		ret = JSString.Value()
	} else if JSString.IsInteger() {
		//web js 中改变成integer类型
		intVal, _ := JSString.IntegerValue()
		ret = fmt.Sprintf("%d", intVal)
	}
	fmt.Println("JSString:", ret, "JSInt:", JSInt.Value(), "JSBool:", JSBool.Value(), "JSDouble:", JSDouble.Value())
	return p1 + " Go返回的值: " + ret
}

src/struct-var.go

定义了结构

package src

import "fmt"

var JSStructVarDemo *StructVarDemo

//定义结构类型的变量
//结构类型将属性和函数导出为JS可调用类型
//大写字母开头
type StructVarDemo struct {
	StringField   string
	IntField      int32
	BoolField     bool
	FloatField    float64
	noExportField string //小写字母无法绑定到js
}

//结构类型的函数导出
func (m *StructVarDemo) StringValue(p0 string) string {
	fmt.Println("结构类型绑定函数 StringValue 被调用 入参:", p0)
	return m.StringField + p0
}

//结构类型的函数导出
func (m *StructVarDemo) IntValue(intParam int32) int32 {
	fmt.Println("结构类型绑定函数 IntValue 被调用 入参:", intParam)
	return m.IntField + intParam
}

//定义导出函数参数最多为9个
func (m *StructVarDemo) FuncMaxParam(p1, p2, p3, p4, p5, p6, p7, p8, p9 string) {
	fmt.Println("结构类型绑定函数 FuncMaxParam 被调用 入参:", p1, p2, p3, p4, p5, p6, p7, p8, p9)
}

html代码示例

在html中直接使用根对象调用函数

通用类型 gocobj.XXX

结构类型 goobj.XXX

通用类型可任意改变值类型(所支持的类型)

结构类型不可改变值类型(只能是go中定义的类型)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>execute-go-bind-js-var</title>
    <script type="application/javascript">
        function clearMessage() {
            document.getElementById("message").innerHTML = "";
        }

        function writeMessage(data) {
            let message = document.getElementById("message");
            message.innerHTML = message.innerHTML + data + "<br>"
        }

        //通过根对象 goobj 和 gocobj 获取或设置值
        //goobj   是结构类型的根对象
        //gocobj  是通用类型的根对象

        /** 结构类型 */
        //获取Go中定义的绑定变量值
        function getGoBindVar() {
            clearMessage()
            writeMessage("结构")
            //------------------------
            //获取结构类型的字段值 string
            writeMessage("StringField: " + goobj.StructVarDemo.StringField)
            writeMessage("IntField: " + goobj.StructVarDemo.IntField)
            writeMessage("BoolField: " + goobj.StructVarDemo.BoolField)
            writeMessage("FloatField: " + goobj.StructVarDemo.FloatField)
            try {
                writeMessage("noExportField 是未导出的字段,将获取失败")
                writeMessage("noExportField: " + goobj.StructVarDemo.noExportField)
            } catch (e) {
                writeMessage("异常: " + e)
            }
        }

        //设置Go中定义的绑定变量值
        function setGoBindVar() {
            clearMessage()
            writeMessage("结构")
            //设置结构类型的字段值 string
            //注意: 结构类型的字段,设置不同类型的值将出现JS异常
            goobj.StructVarDemo.StringField = "在Web中改变后的值"
            goobj.StructVarDemo.IntField = 999999
            goobj.StructVarDemo.BoolField = true
            goobj.StructVarDemo.FloatField = 99999.9999
            try {
                writeMessage("StringField=int 不同的类型赋值将出现异常")
                //不同的类型赋值将出现异常
                goobj.StructVarDemo.StringField = 1001
            } catch (e) {
                writeMessage("异常: " + e)
            }
        }

        //调用Go中定义的函数
        function callGoBindFunc() {
            clearMessage()
            writeMessage("结构")
            //在JS中调用Go的函数
            //注意:同字段一样函数首字母只有大写才能调用
            //     入参类型必须符合Go中函数定义的参数类型, 否则调用失败, 注意的是参数个数有限制
            let ret = goobj.StructVarDemo.StringValue(' JS传的入参')
            writeMessage("调用函数 StringValue(param0 string) string: " + ret)
            goobj.StructVarDemo.FuncMaxParam('参数1', '参数2', '参数3', '参数4', '参数5', '参数6', '参数7', '参数8', '参数9')
            try {
                writeMessage("FuncMaxParam 函数和入参个数大于9个调用失败")
                //参数个数大于9个调用失败
                goobj.StructVarDemo.FuncMaxParam('参数1', '参数2', '参数3', '参数4', '参数5', '参数6', '参数7', '参数8', '参数9', '参数10')
            } catch (e) {
                writeMessage("异常: " + e)
            }
        }

        /** 普通类型 */
        //获取通用变量类型值
        function getGoBindCVar() {
            clearMessage()
            writeMessage("通用类型")
            writeMessage('JSString: ' + gocobj.JSString)
            writeMessage('JSInt: ' + gocobj.JSInt)
            writeMessage('JSBool: ' + gocobj.JSBool)
            writeMessage('JSDouble: ' + gocobj.JSDouble)
        }

        function setGoBindCVar() {
            clearMessage()
            writeMessage("通用类型")
            //通用类型可以任意修改变量存放的值类型
            gocobj.JSString = 'JS中改变了通用类型字符串值'
            writeMessage('JSString值改变: ' + gocobj.JSString)
            //改变为其它类型后,在Go中使用时需要判断类型,否则类型不一样无法正确取值
            gocobj.JSString = 99999
            writeMessage('JSString值变成了Int类型: ' + gocobj.JSString)
            //将其它变量值改变
            gocobj.JSInt = 999911
            gocobj.JSBool = true
            gocobj.JSDouble = 999999.999
        }

        function callGoBindCFunc() {
            clearMessage()
            writeMessage("通用类型")
            writeMessage('调用JSFunc函数: ' + gocobj.JSFunc('JS传入的参数'))
        }

        /** to json */
        function toJSON() {
            clearMessage()
            writeMessage("ToJSON")
            writeMessage('结构类型-JSON: ' + JSON.stringify(goobj))
            writeMessage('通用类型-JSON: ' + JSON.stringify(gocobj))
        }
    </script>
</head>
<body style="overflow: hidden;margin: 0px;padding: 0px;">
execute-go-bind-js-var:<br>
<div style="margin: 10px">
    结构类型:
    <button onclick="getGoBindVar()">获取Go中定义的绑定变量值</button>
    <button onclick="setGoBindVar()">设置Go中定义的绑定变量值</button>
    <button onclick="callGoBindFunc()">调用Go中定义的函数</button>
</div>
<div style="margin: 10px">
    通用类型:
    <button onclick="getGoBindCVar()">获取Go中定义的通用类型绑定变量值</button>
    <button onclick="setGoBindCVar()">设置Go中定义的通用类型绑定变量值</button>
    <button onclick="callGoBindCFunc()">调用Go中定义的函数</button>
</div>
<div style="margin: 10px">
    <button onclick="toJSON()">toJSON</button>
</div>
<div id="message"></div>
</body>
</html>

效果图