Golang模板无法提供WASM服务的解决方法

Golang模板无法提供WASM服务的解决方法 简述: 我有一个使用WebAssembly文件的HTML文件,如果通过Golang服务器作为静态文件加载,一切运行正常。但如果作为模板加载,WebAssembly文件就无法运行,并出现以下错误:

localhost/:1 Uncaught (in promise) CompileError: WebAssembly.compile(): expected magic word 00 61 73 6d, found 3c 21 44 4f @+0

详细说明: 我有以下HTML文件:

<!DOCTYPE html>
<html>
<head>
  <title>Golang WebAssembly Example</title>
</head>
<body>
  <button onclick="handleClick()">Click me</button>
  <button onclick="callHandleData()">handleData</button>
  <button onclick="notifyme()">notifyme</button>
  <div id="result"></div>
  <script src="/script/wasm_exec.js"></script>
  <script>
    const go = new Go();
    let wasm;

    fetch('main.wasm').then(response =>
      response.arrayBuffer()
    ).then(bytes => WebAssembly.instantiate(bytes, go.importObject)).then(result => {
      wasm = result.instance;
      go.run(wasm); // This will start the Go runtime
    })

    function callHandleData() {
        let data = handleData(46, "Hello, World!");
        // Parse the data using JSON.parse  // Parse the data using JSON.parse
        let parsedData = JSON.parse(data);  // Double stringify for safety

        // Access the text property from the parsed object
        let text = parsedData.text;
        let num = parsedData.number;
        alert(data)
        alert(text + " What is the "+ num);  // Or use text for further manipulation
    }
  </script>
</body>
</html>

我尝试通过Golang中的模板加载它,如下所示,但遇到了上述错误:

package main

import (
	"html/template"
	"net/http"
	"path/filepath"
)

func handler(w http.ResponseWriter, r *http.Request) {

	baseTmpl, err := template.ParseFiles("wasm.html")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	err = baseTmpl.ExecuteTemplate(w, "wasm.html", nil) // Pass nil as data
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func main() {
	http.HandleFunc("/", handler)

	// Serve static files
	http.HandleFunc("/script/", func(w http.ResponseWriter, r *http.Request) {
		filePath := r.URL.Path[len("/script/"):]
		if filepath.Ext(filePath) == ".wasm" {
			w.Header().Set("Content-Type", "application/wasm")
		}
		http.ServeFile(w, r, "script/"+filePath)
	})

	http.ListenAndServe(":8080", nil)
}

更多关于Golang模板无法提供WASM服务的解决方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang模板无法提供WASM服务的解决方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题在于模板引擎会对HTML文件进行转义处理,导致WASM文件的二进制内容被破坏。当作为静态文件服务时,WASM文件保持原始二进制格式;但通过模板加载时,HTML模板引擎会对特殊字符进行转义,破坏了WASM文件的二进制结构。

错误信息中的 3c 21 44 4f 对应ASCII字符 <!DO,这正是HTML文档的开头部分,说明浏览器尝试将HTML文档作为WASM文件解析。

解决方案:

将HTML文件作为静态文件服务,而不是通过模板引擎加载。修改后的代码:

package main

import (
	"net/http"
	"path/filepath"
)

func main() {
	// 直接提供静态HTML文件
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path == "/" {
			http.ServeFile(w, r, "wasm.html")
			return
		}
		http.NotFound(w, r)
	})

	// 提供静态文件服务(包括WASM文件)
	http.HandleFunc("/script/", func(w http.ResponseWriter, r *http.Request) {
		filePath := r.URL.Path[len("/script/"):]
		if filepath.Ext(filePath) == ".wasm" {
			w.Header().Set("Content-Type", "application/wasm")
		}
		http.ServeFile(w, r, "script/"+filePath)
	})

	http.ListenAndServe(":8080", nil)
}

如果需要使用模板功能(例如动态注入数据),可以采用以下方法:

package main

import (
	"html/template"
	"net/http"
	"path/filepath"
)

func handler(w http.ResponseWriter, r *http.Request) {
	// 解析模板但不执行转义
	tmpl, err := template.New("wasm.html").ParseFiles("wasm.html")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// 执行模板
	err = tmpl.Execute(w, nil)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func main() {
	http.HandleFunc("/", handler)

	// 提供WASM文件的静态服务
	http.HandleFunc("/script/", func(w http.ResponseWriter, r *http.Request) {
		filePath := r.URL.Path[len("/script/"):]
		if filepath.Ext(filePath) == ".wasm" {
			w.Header().Set("Content-Type", "application/wasm")
		}
		http.ServeFile(w, r, "script/"+filePath)
	})

	http.ListenAndServe(":8080", nil)
}

关键点:

  1. WASM文件必须是原始的二进制格式,不能经过任何转义或编码处理
  2. 确保WASM文件的Content-Type正确设置为application/wasm
  3. 如果HTML文件不需要动态内容,直接作为静态文件服务是最简单可靠的方式
  4. 如果必须使用模板,确保模板引擎不会对WASM文件的引用路径进行修改或转义
回到顶部