golang实现Go与JS值互操作插件库vert的使用
vert - Go与JS值互操作插件库
vert是一个用于在WebAssembly环境中实现Go与JavaScript值互操作的库。
安装
GOOS=js GOARCH=wasm go get github.com/norunners/vert
使用示例
基础类型互操作
package main
import "github.com/norunners/vert"
func main() {
v := vert.ValueOf("Hello World!")
// 将v作为JS值使用
s := ""
v.AssignTo(&s)
// 将s作为Go值使用
}
结构体与对象互操作
package main
import "github.com/norunners/vert"
type Data struct {
Message string
}
func main() {
v := vert.ValueOf(Data{
Message: "Hello World!",
})
// 转换为JS对象,如{"Message": "Hello World!"}
d := &Data{}
v.AssignTo(d)
}
带标签的结构体字段
package main
import "github.com/norunners/vert"
type Data struct {
Message string `js:"msg"` // 使用js标签指定JS中的字段名
}
func main() {
v := vert.ValueOf(Data{
Message: "Hello World!",
})
// 转换为JS对象,如{"msg": "Hello World!"}
d := &Data{}
v.AssignTo(d)
}
错误处理
package main
import "github.com/norunners/vert"
type Data struct {
Message string
}
func main() {
v := vert.ValueOf("Hello World!")
d := &Data{}
if err := v.AssignTo(d); err != nil {
// 处理错误
}
}
vert解决的问题
Go标准库中的syscall/js
对Go与JS值互操作的支持有限:
js.ValueOf
不接受结构体类型,会导致panicjs.Value
类型不支持非基本Go值的Interface
或赋值方法
vert扩展了syscall/js
的功能,解决了这些限制。
完整示例
package main
import (
"fmt"
"github.com/norunners/vert"
)
// 定义带有JS标签的结构体
type User struct {
ID int `js:"user_id"`
Name string `js:"username"`
Email string `js:"email"`
Active bool `js:"is_active"`
}
func main() {
// 创建Go结构体实例
goUser := User{
ID: 1,
Name: "John Doe",
Email: "john@example.com",
Active: true,
}
// 转换为JS值
jsValue := vert.ValueOf(goUser)
// 这里jsValue可以传递给JS代码使用
// 从JS值转换回Go结构体
var newUser User
if err := jsValue.AssignTo(&newUser); err != nil {
fmt.Println("转换错误:", err)
return
}
fmt.Printf("转换结果: %+v\n", newUser)
}
这个示例展示了如何:
- 定义一个带有JS字段标签的结构体
- 将Go结构体转换为JS值
- 将JS值转换回Go结构体
- 处理可能出现的错误
vert库使得在WebAssembly环境中Go与JavaScript之间的数据交换变得简单高效。
更多关于golang实现Go与JS值互操作插件库vert的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang实现Go与JS值互操作插件库vert的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Go与JS值互操作插件库vert的使用指南
vert是一个轻量级的Go插件库,专门用于简化Go与JavaScript之间的值互操作。下面我将详细介绍vert的使用方法,并提供相应的Go代码示例。
安装vert
首先,使用go get安装vert库:
go get github.com/norunners/vert
基本用法
1. 将Go值转换为JS值
package main
import (
"github.com/norunners/vert"
"syscall/js"
)
func main() {
// 初始化JS运行时
js.Global().Get("console").Call("log", "Starting vert demo...")
// 基本类型转换
goInt := 42
jsValue := vert.ValueOf(goInt)
js.Global().Get("console").Call("log", "Go int to JS:", jsValue)
// 结构体转换
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 30}
jsPerson := vert.ValueOf(p)
js.Global().Get("console").Call("log", "Go struct to JS:", jsPerson)
// 切片转换
goSlice := []string{"apple", "banana", "cherry"}
jsSlice := vert.ValueOf(goSlice)
js.Global().Get("console").Call("log", "Go slice to JS:", jsSlice)
}
2. 将JS值转换为Go值
func jsToGo() {
// 假设我们有一个JS对象
jsObj := js.Global().Get("Object").New()
jsObj.Set("name", "Bob")
jsObj.Set("age", 25)
jsObj.Set("hobbies", []interface{}{"reading", "swimming"})
// 转换为Go的map
var goMap map[string]interface{}
vert.Assign(&goMap, jsObj)
println("JS to Go map:", goMap["name"], goMap["age"])
// 转换为结构体
type JsPerson struct {
Name string `js:"name"`
Age int `js:"age"`
Hobbies []string `js:"hobbies"`
}
var person JsPerson
vert.Assign(&person, jsObj)
println("JS to Go struct:", person.Name, person.Age)
}
高级特性
1. 处理复杂嵌套结构
type Address struct {
Street string `js:"street"`
City string `js:"city"`
}
type User struct {
Name string `js:"name"`
Age int `js:"age"`
Address Address `js:"address"`
Tags []string `js:"tags"`
}
func handleComplexStruct() {
// 创建JS复杂对象
jsUser := js.Global().Get("Object").New()
jsUser.Set("name", "Charlie")
jsUser.Set("age", 35)
jsAddress := js.Global().Get("Object").New()
jsAddress.Set("street", "123 Main St")
jsAddress.Set("city", "Metropolis")
jsUser.Set("address", jsAddress)
jsTags := vert.ValueOf([]string{"admin", "developer"})
jsUser.Set("tags", jsTags)
// 转换为Go结构体
var user User
vert.Assign(&user, jsUser)
fmt.Printf("User: %+v\n", user)
}
2. 处理函数回调
func registerCallback() {
// 将Go函数暴露给JS
callback := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
// 将JS参数转换为Go值
var goArgs []interface{}
vert.Assign(&goArgs, args)
fmt.Println("Callback received:", goArgs)
return nil
})
js.Global().Set("goCallback", callback)
// 在JS中可以这样调用: goCallback("hello", 123, {key: "value"})
}
3. 性能优化技巧
对于频繁调用的场景,可以预先创建转换器:
func optimizedConversion() {
// 预编译转换器
type Point struct {
X int `js:"x"`
Y int `js:"y"`
}
converter := vert.NewConverter(Point{})
// 多次使用同一个转换器
jsPoint := js.Global().Get("Object").New()
jsPoint.Set("x", 10)
jsPoint.Set("y", 20)
var p1, p2 Point
converter.Assign(&p1, jsPoint)
converter.Assign(&p2, jsPoint)
fmt.Println("Optimized conversion:", p1, p2)
}
注意事项
- vert不支持循环引用的数据结构
- 转换大型数据结构时注意性能影响
- 结构体字段标签
js:"fieldName"
是可选的,但建议显式声明 - 处理JS的null/undefined时,Go中对应的零值
完整示例
package main
import (
"fmt"
"syscall/js"
"github.com/norunners/vert"
)
func main() {
// 等待前端加载完成
done := make(chan struct{})
// 注册Go函数供JS调用
js.Global().Set("goAdd", js.FuncOf(add))
// 演示JS调用Go函数
js.Global().Call("eval", `
console.log("Calling Go function from JS...");
const result = goAdd(5, 7);
console.log("Result from Go:", result);
`)
<-done
}
func add(this js.Value, args []js.Value) interface{} {
var a, b int
vert.Assign(&a, args[0])
vert.Assign(&b, args[1])
sum := a + b
return vert.ValueOf(sum)
}
vert库通过简单的API简化了Go和JS之间的数据交换,特别适合WebAssembly场景。使用时注意类型映射关系,对于复杂场景可以结合性能优化技巧提升效率。