Скомпилируйте инструмент Go в wasm

Go

причина

Некоторое время назад я написал инструмент для генерации документации по API.mkdoc, потому что он не полагается на go CLI, как swag-go. Позже я задался вопросом, могу ли я скомпилировать его в wasm и разместить на веб-странице, чтобы каждый мог понять его после развертывания 0.

достижение

👉 Онлайн опыт 👈

  • ( :

если ты правmkdocЗаинтересованы, добро пожаловать в fork&star

некоторые проблемы

  1. Файловая система используется в инструменте, и файловая система не реализована в wasm_exec.js, предоставленном go
  2. Используется системный вызов os.Getwd, который напрямую не поддерживается syscall/js.
  3. Некоторые проблемы взаимодействия между go и js

решить

Файловая система

Нереализованный можно увидеть в wasm_exec.js.node fs API, то нам просто нужно следоватьnode fs APIреализоватьmemory filesystem, можно решить проблему с файловой системой.

Но строить колесо самостоятельно слишком хлопотно, поэтому я его искалmemfsЭта библиотека (100 👍 автору). В случае с memfs я назначаю предоставленную им fs для window.fs в соответствии с тем, как он ее использует, и go будет использовать эту fs.

системный вызов

Посмотрите исходный код os.Getwd

// Getwd returns a rooted path name corresponding to the
// current directory. If the current directory can be
// reached via multiple paths (due to symbolic links),
// Getwd may return any one of them.
func Getwd() (dir string, err error) {
	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
		return syscall.Getwd()
	}

	// Clumsy but widespread kludge:
	// if $PWD is set and matches ".", use it.
	dot, err := statNolog(".")
	if err != nil {
		return "", err
	}
	dir = Getenv("PWD")
	if len(dir) > 0 && dir[0] == '/' {
		d, err := statNolog(dir)
		if err == nil && SameFile(dot, d) {
			return dir, nil
		}
	}

Установлено, что он проверит переменную окружения PWD, если обнаружится, что она в данный момент$PWDЗначение $PWD будет использоваться напрямую, Таким образом, добавление набора env при запуске может получить каталог getwd неверно.

func initJS() {
	//...
	os.Setenv("PWD", "/")
}

взаимодействовать

Здесь я в основном пишу метод для привязки go log.Println к js console.log, а вы можете прочитать документацию для других.

func (c *ConsoleWriter) Write(p []byte) (n int, err error) {
	js.Global().Get("console").Call("log", string(p))
	return len(p), nil
}

func (c *ConsoleWriter) Log(s string) {
	c.Write([]byte(s))
}

var console = new(ConsoleWriter)

func initJS() {
	log.SetOutput(console)
	// ...
}