V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
ansi395958
V2EX  ›  分享创造

把一个 Go 工具编译到 wasm

  •  1
     
  •   ansi395958 · 2020-08-11 00:07:25 +08:00 · 2542 次点击
    这是一个创建于 1558 天前的主题,其中的信息可能已经有所发展或是发生改变。

    起因

    前段时间写了个 API 文档生成工具mkdoc,因为并没有像 swag-go 一样依赖 go CLI 后来就在想能不能把他编译到 wasm 然后放到网页上,这样就能方便大家 0 部署就能对他有个了解。

    成果

    👉 在线体验 👈

    • ( : 如果你对mkdoc感兴趣,欢迎 fork&star

    一些问题

    1. 工具里用到了文件系统,go 提供的 wasm_exec.js 中没有实现文件系统
    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 的值, 所以在启动的时候加一句 set 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)
    	// ...
    }
    
    
    2 条回复    2020-08-11 19:05:23 +08:00
    somalia
        1
    somalia  
       2020-08-11 00:56:48 +08:00
    Fork
    Fork
    Fork
    ansi395958
        2
    ansi395958  
    OP
       2020-08-11 19:05:23 +08:00
    @somalia STAR STAR STAR
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2549 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 01:20 · PVG 09:20 · LAX 17:20 · JFK 20:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.