如果熟悉Go Playground,那么就会知道在浏览器中安装Go暂存器有多方便。想给别人看一段代码片段吗?是否想快速测试一些语法?基于浏览器的代码垫很有帮助。关于这一点,我创建了一个新的游乐场。关于这个新游乐场的妙处在于,它不使用远程服务器来运行代码,而只是用于对其进行编译。该代码在您的浏览器中使用Web Assembly运行。
它是如何工作的?
当用户单击“运行”时,代码将发送回我们的服务器。服务器是用Go语言编写的。因此,API的处理程序如下所示:
func compileCodeHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
// Get code from params
type parameters struct {
Code string
}
decoder := json.NewDecoder(r.Body)
params := parameters{}
err := decoder.Decode(¶ms)
if err != nil {
respondWithError(w, 500, "Couldn't decode parameters")
return
}
// create file system location for compilation path
usr, err := user.Current()
if err != nil {
respondWithError(w, 500, "Couldn't get system user")
return
}
workingDir := filepath.Join(usr.HomeDir, ".wasm", uuid.New().String())
err = os.MkdirAll(workingDir, os.ModePerm)
if err != nil {
respondWithError(w, 500, "Couldn't create directory for compilation")
return
}
defer func() {
err = os.RemoveAll(workingDir)
if err != nil {
respondWithError(w, 500, "Couldn't clean up code from compilation")
return
}
}()
f, err := os.Create(filepath.Join(workingDir, "main.go"))
if err != nil {
respondWithError(w, 500, "Couldn't create code file for compilation")
return
}
defer f.Close()
dat := []byte(params.Code)
_, err = f.Write(dat)
if err != nil {
respondWithError(w, 500, "Couldn't write code to file for compilation")
return
}
// compile the wasm
const outputBinary = "main.wasm"
os.Setenv("GOOS", "js")
os.Setenv("GOARCH", "wasm")
cmd := exec.Command("go", "build", "-o", outputBinary)
cmd.Dir = workingDir
stderr, err := cmd.StderrPipe()
if err != nil {
respondWithError(w, 500, err.Error())
return
}
if err := cmd.Start(); err != nil {
respondWithError(w, 500, err.Error())
return
}
stdErr, err := ioutil.ReadAll(stderr)
if err != nil {
respondWithError(w, 500, err.Error())
return
}
stdErrString := string(stdErr)
if stdErrString != "" {
parts := strings.Split(stdErrString, workingDir)
if len(parts) < 2 {
respondWithError(w, 500, stdErrString)
return
}
respondWithError(w, 400, parts[1])
return
}
if err := cmd.Wait(); err != nil {
respondWithError(w, 500, err.Error())
return
}
// write wasm binary to response
dat, err = ioutil.ReadFile(filepath.Join(workingDir, outputBinary))
if err != nil {
respondWithError(w, 500, err.Error())
return
}
w.Write(dat)
}
如您所见,处理程序仅将代码作为输入,并以WASM字节片作为响应。
前端呢?
前端非常简单。首先,我们需要在页面中包括Go WASM的官方执行者。假设您的计算机上已安装Go,可以在以下位置找到此JavaScript文件:
$(go env GOROOT)/misc/wasm/wasm_exec.js
然后在您的html正文中包含脚本:
<!DOCTYPE html>
<html>
<head>
<title>Qvault Classroom - Learn Coding</title>
</head>
<body>
<script src="wasm_exec.js"></script>
</body>
</html>
因为Qvault Classroom的前端是作为Vue.js单页应用程序编写的,所以我创建了一个小的es6模块,该模块运行WASM字节数组并将输出作为行数组返回:
const go = new window.Go();export default async function runGoWasm(rawData) {
const result = await WebAssembly.instantiate(rawData, go.importObject);
let oldLog = console.log;
let stdOut = [];
console.log = (line) => {stdOut.push(line);};
await go.run(result.instance);
console.log = oldLog;
return stdOut;
}
关于如何使用Web Assembly在浏览器中运行Go 的内容,介绍到这里就结束了。如果还想了解更多关于Web Assembly的信息,请继续关注中培伟业。