介绍
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>
效果图