英文:
Export function from GO compiling WASM
问题
嗨,我想将一个GO文件编译成WASM,并从一个Node服务器上运行它。
在index.html
中,我有以下代码:
<script src="./path_to/wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("./path_to/file.wasm"), go.importObject).then((result) => {
go.run(result.instance);
console.log(result);
console.log(go);
});
我编译成WASM的GO文件如下所示:
package main
import (
"fmt"
)
//export FuncName
func FuncName(M int, durations []int) int {
fmt.Println("[GO] Log file.go", M, durations)
return 10
}
func main() {
fmt.Println("HELLO GO")
}
我目前使用以下命令进行编译:
GOOS=js GOARCH=wasm go build -o path_to/file.wasm path_to/file.go
我想在Go文件外部和HTML内部使用FuncName函数,但我无法导出它。
我尝试使用tinygo,像这样:tinygo build -o path_to/file.wasm path_to/file.go
,但它也没有起作用。
英文:
Hi I want to make a compile a GO file intro WASM and run in from a node server.
In the index.html
i have this:
<script src="./path_to/wasm_exec.js" ></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("./path_to/file.wasm"), go.importObject).then((result) => {
go.run(result.instance);
console.log(result);
console.log(go);
});
The GO file I compile to WASM is like this one:
package main
import (
"fmt"
)
//export FuncName
func FuncName(M int, durations []int) int {
fmt.Println("[GO] Log file.go", M, durations)
return 10
}
func main() {
fmt.Println("HELLO GO")
}
And I compile Im currently compiling using this:
GOOS=js GOARCH=wasm go build -o path_to/file.wasm path_to/file.go
I want to use the funtion FuncName outside the Go file, and inside the html but i can export it.
I tried using tinygo like this: `tinygo build -o path_to/file.wasm path_to/file.go``but it didint work neather
答案1
得分: 1
纯Go的方法是使用syscall/js
包将函数挂载在JavaScript全局对象上(通常是window
或global
):
js.Global().Set("myexport", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
//stuff
})
为了使导出的函数始终在页面上可用,Go程序不应该退出。否则,在调用导出的函数时,您将收到以下JavaScript错误:
Uncaught Error: Go program has already exited
请参阅wasm: re-use //export mechanism for exporting identifiers within wasm modules和https://stackoverflow.com/questions/67978442/go-wasm-export-functions。
这是一个更新的演示,可以正常工作(使用GOOS=js GOARCH=wasm go build -o main.wasm
编译):
main.go:
package main
import (
"fmt"
"syscall/js"
)
func FuncName(M int, durations []int) int {
fmt.Println("[GO] Log file.go", M, durations)
return 10
}
func main() {
fmt.Println("Hello, WebAssembly!")
// 将函数挂载在JavaScript全局对象上。
js.Global().Set("FuncName", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
if len(args) != 2 {
fmt.Println("invalid number of args")
return nil
}
if args[0].Type() != js.TypeNumber {
fmt.Println("the first argument should be a number")
return nil
}
arg := args[1]
if arg.Type() != js.TypeObject {
fmt.Println("the second argument should be an array")
return nil
}
durations := make([]int, arg.Length())
for i := 0; i < len(durations); i++ {
item := arg.Index(i)
if item.Type() != js.TypeNumber {
fmt.Printf("the item at index %d should be a number\n", i)
return nil
}
durations[i] = item.Int()
}
// 调用实际的函数。
return FuncName(args[0].Int(), durations)
}))
// 防止程序退出。
// 注意:如果不再需要导出的函数,应该释放它,并在此之后让程序退出。
// 为了简化这个演示,这一步被省略了。有关更多信息,请参阅https://pkg.go.dev/syscall/js#Func.Release。
select {}
}
index.html:
<html>
<head>
<meta charset="utf-8" />
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(
fetch('main.wasm'),
go.importObject
).then((result) => {
go.run(result.instance);
});
</script>
</head>
<body>
<button id="btn">Call FuncName</button>
<script>
document.getElementById('btn').addEventListener('click', () => {
console.log(FuncName(1, [1, 2, 3, 4, 5]));
});
</script>
</body>
</html>
英文:
The pure Go way is to mount the function on the JavaScript global object (usually window
or global
) with the syscall/js
package:
js.Global().Set("myexport", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
//stuff
})
And to make the exported function always available on the page, the Go program should not exit. Otherwise, you will get this JavaScript error when calling the exported function:
Uncaught Error: Go program has already exited
See also wasm: re-use //export mechanism for exporting identifiers within wasm modules and https://stackoverflow.com/questions/67978442/go-wasm-export-functions.
Here is updated demo that works (compiled with GOOS=js GOARCH=wasm go build -o main.wasm
):
main.go:
package main
import (
"fmt"
"syscall/js"
)
func FuncName(M int, durations []int) int {
fmt.Println("[GO] Log file.go", M, durations)
return 10
}
func main() {
fmt.Println("Hello, WebAssembly!")
// Mount the function on the JavaScript global object.
js.Global().Set("FuncName", js.FuncOf(func(this js.Value, args []js.Value) any {
if len(args) != 2 {
fmt.Println("invalid number of args")
return nil
}
if args[0].Type() != js.TypeNumber {
fmt.Println("the first argument should be a number")
return nil
}
arg := args[1]
if arg.Type() != js.TypeObject {
fmt.Println("the second argument should be an array")
return nil
}
durations := make([]int, arg.Length())
for i := 0; i < len(durations); i++ {
item := arg.Index(i)
if item.Type() != js.TypeNumber {
fmt.Printf("the item at index %d should be a number\n", i)
return nil
}
durations[i] = item.Int()
}
// Call the actual func.
return FuncName(args[0].Int(), durations)
}))
// Prevent the program from exiting.
// Note: the exported func should be released if you don't need it any more,
// and let the program exit after then. To simplify this demo, this is
// omitted. See https://pkg.go.dev/syscall/js#Func.Release for more information.
select {}
}
index.html:
<html>
<head>
<meta charset="utf-8" />
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(
fetch('main.wasm'),
go.importObject
).then((result) => {
go.run(result.instance);
});
</script>
</head>
<body>
<button id="btn">Call FuncName</button>
<script>
document.getElementById('btn').addEventListener('click', () => {
console.log(FuncName(1, [1, 2, 3, 4, 5]));
});
</script>
</body>
</html>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论