从 Go 语言诞生以来,它就开始不断侵蚀 Java 、C、C++ 语言的领地。今年下半年 Go 语言发布了 1.11 版本,引入了 WebAssembly 技术,浏览器端 Javascript 的垄断地位也开始遭遇 Go 语言的攻击。这次不同以往,它意味着 Go 语言从后端渗透进了前端,进入了一个全新的世界。

WebAssembly 运行原理

WebAssembly 这个名字翻译过来就是 「Web 汇编」,也就是 Web 端的汇编语言。它是一段二进制字节码程序,Javascript 可以将这段二进制程序编译成模块,然后再实例化这个模块就可以调用字节码逻辑了。WebAssembly 代码运行的速度很快,比 Javascript 要快很多,Javascript 可以通过 WebAssembly 技术将关键性耗费性能的逻辑交给 WebAssembly 来做就可以明显提升浏览器端的性能。

对比显示,使用 WebAssembly 运行斐波那契数列相比使用原生 Javascript 来实现,运行效率上能带来 3.5 倍的提升。

WebAssembly 是一项比较新的技术,只有比较现代的浏览器才支持 WebAssembly,例如 Chrome、FireFox浏览器。

Go WebAssembly 运行原理

Go 编译器可以将代码编译成 WebAssembly 二进制字节码,被浏览器以静态资源的形式加载进来后转换成 Javascript 模块。有了这个模块,浏览器可以直接操纵 Go 语言生成的二进制字节码逻辑。同时在 Go 语言编写的代码中可以直接读写浏览器里面 Javascript 运行时对象,这样就完成了 Javascript 和 Go 代码的双向交互。

Go 语言直到 1.11 版本之后才开启了对 WebAssembly 的支持。如需体验,必须升级。

Go WebAssembly 初体验

下面我们就开始体验一下 Chrome 浏览器与 Go 代码是如何交互的。我们要实现一个功能,在浏览器的输入框里输入一个正整数,然后调用 Go 代码的斐波那契数列,再将结果再呈现在页面上。涉及到 4 个文件,分别是 fib.go、main.go、index.html、wasm_exec.js。

第一步

使用 Go 代码编写 WebAssembly 模块文件 fib.go,将 Go 语言实现的斐波那契函数注册到 Javascript 全局环境。这需要使用内置的 syscall/js 模块,它提供了和 Javascript 引擎交互的接口。

// fib.go
package mainimport "syscall/js"func main() {f_fib := func(params []js.Value) {var n = params[0].Int() // 输入参数var callback = params[1] // 回调参数var result = fib(n)// 调用回调函数,传入计算结果callback.Invoke(result)}// 注册全局函数js.Global().Set("fib", js.NewCallback(f_fib))// 保持 main 函数持续运行select {}
}// 计算斐波那契数
func fib(n int) int {if n <= 0 {return 0}var result = make([]int, n+1)result[0] = 0result[1] = 1if n <= 1 {return result[n]}for i:=2;i<=n;i++ {result[i] = result[i-2] + result[i-1]}return result[n]
}
复制代码

Go 语言注册到 Javascript 引擎的函数在执行时是异步的,所以这个函数没有返回值,在完成计算后需要通过调用「传进来的回调函数」将结果传递到 Javascript 引擎。注意 main 函数要保持运行状态不要退出,不然注册进去的 fib 函数体就销毁了。

第二步

下面将 Go 代码编译成 WebAssembly 二进制字节码。

$ GOARCH=wasm GOOS=js go build -o fib.wasm fib.go
复制代码

执行完成后可以看到目录下多了一个 fib.wasm,这个就是字节码文件。它的大小是 1.3M,作为静态文件传递到浏览器似乎有点大,不过静态文件服务器一般有 gzip 压缩,压缩后的大小只有几百K,这差不多也可以接受了。

第三步

编写网页文件 index.html,这个网页包含两个输入框,第一个输入框用来输入整数参数,第二个输入框用来呈现计算结果。当第一个输入框内容发生改变时,调用 javascript 代码,执行通过 WebAssembly 注册的 fib 函数。需要传入参数 n 和回调的函数。

<html><head><meta charset="utf-8"><title>Go wasm</title>
</head><style>
body {text-align: center
}
input {height: 50px;font-size: 20px;
}
#result {margin-left: 20px;
}
</style><body><script src="wasm_exec.js"></script><script>// 容纳 WebAssembly 模块的容器var go = new Go();// 下载 WebAssembly 模块并执行模块// 也就是运行 Go 代码里面的 main 函数// 这样 fib 函数就注册进了 Javascript 全局环境WebAssembly.instantiateStreaming(fetch("fib.wasm"), go.importObject).then((result) => {go.run(result.instance);});function callFib() {let paramInput = document.getElementById("param")let n = parseInt(paramInput.value || "0")// 传入输入参数和回调函数// 回调函数负责呈现结果fib(n, function(result) {var resultDom = document.getElementById("result")resultDom.value = result})}</script>// 输入发生变化时,调用 WebAssembly 的 fib 函数<input type="number" id="param" oninput="callFib()"/><input type="text" id="result" />
</body></html>
复制代码

注意代码中引入了一个特殊的 js 文件 wasm_exec.js,这个文件可以从 Go 安装目录的 misc 子目录里找到,将它直接拷贝过来。它实现了和 WebAssembly 模块交互的功能。

第四步

运行静态文件服务器,这里不能使用普通的静态文件服务器,因为浏览器要求请求到的 WebAssemly 字节码文件的 Content-Type 必须是 application/wasm,很多静态文件服务器并不会因为扩展名是 wasm 就会自动使用这个 Content-Type。但是 Go 内置的 HTTP 服务器可以。所以下面我们使用 Go 代码简单编写一个静态文件服务器。

package mainimport ("log""net/http"
)func main() {mux := http.NewServeMux()mux.Handle("/", http.FileServer(http.Dir(".")))log.Fatal(http.ListenAndServe(":8000", mux))
}
复制代码

使用下面的命令运行它

$ go run main.go
复制代码

第五步

打开浏览器,访问 http://localhost:8000,现在就可以体验它的运行效果了。

Javascript 真的需要担心 Go WebAssembly 的威胁么?

其实根本不用担心,WebAssembly 的目的是替换前端运行比较耗时的逻辑,不是用来替换前端框架的,它也替换不了。虽然开源社区冒出了一个 github.com/elliotforbe… 的 Go WebAssembly 框架,可以让你使用 Go 语言编写前端应用程序。但是我仔细看了一下它的的源码,发现它原来只是一个玩具 ^_^,实现上没几行代码,离真实的应用程序差距太远。

如果 Go WebAssembly 对 javascript 是个威胁,那么威胁 javascript 的可不止 Go 语言了,能够将代码编译成 WebAssembly 字节码的语言多达几十种。

希望将当前 javascript 项目的部分代码替换成 Go 语言,成本也是显而易见的。技术栈的切换成本,字节码的加载成本,框架项目持续集成的成本都是需要考虑的点。除非能获得巨大的性能提升,否则使用纯粹的 javascript 来完成项目依然是最佳选择。

微信搜索「codehole」,关注公众号「码洞」

不安分的 Go 语言开始入侵 Web 前端领域了相关推荐

  1. 不安分的 Go 语言开始入侵 Web 前端领域了!

    作者 | 老钱 责编 | 胡巍巍 本文经授权转载自"码洞"(ID:codehole) 从 Go 语言诞生以来,它就开始不断侵蚀 Java .C.C++ 语言的领地.今年下半年 Go ...

  2. 2019年的web前端领域

    web前端教程 用大白话,来讲编程 查看全文 http://www.taodudu.cc/news/show-1159841.html 相关文章: [ IT版 ]啥是佩奇? 上线当天程序员锁死服务器, ...

  3. html语言入门测试题,Web前端:20道非常基础的JavaScript测试题

    1.我们可以在下列哪个 HTML 元素中放置 Javascript 代码?() A. B. C. D. 2.写 "Hello World" 的正确 Javascript 语法是?( ...

  4. js 调用c语言函数看,web前端:JS高级---函数中的this的指向,函数的不同调用方式...

    在程序设计中,常将一些常用的功能模块编写成函数,放在函数库中供公共选用.要善于利用函数,以减少重复编写程序段的工作量. 函数分为全局函数.全局静态函数;在类中还可以定义构造函数.析构函数.拷贝构造函数 ...

  5. Web前端就业薪资是多少?Web前端要学什么?

    Web前端开发作为实现前台页面展示的主要技术手段,已经越来越被大众所熟知,很多人也因此对Web前端产生了兴趣,萌生了想要学习Web前端的想法.那,Web前端就业薪资是多少?Web前端要学什么?今天,小 ...

  6. 为什么要选择学Web前端?无法反驳的4大理由

    如今的互联网行业一直流传着一句话:"用户至上",想要提升用户体验,Web前端的作用非常重要.所以,很多人看准了这一点纷纷想要转行做Web前端开发.因为对Web前端行业不了解,在学习 ...

  7. Web前端新手必看的7种技术,从菜鸟到高级开发的蜕变!

    随着互联网发展,Web前端开发逐渐走红.由于大学没有开设前端课程,知识体系不够规范完整,每个人对它的认识也各不相同,加之互联网技术更新迭代迅速今天给你解读一下,学习Web前端的基本需要掌握的知识. 具 ...

  8. Web前端新手必备的知识点,大家都掌握了吗?

    一名合格的web前端工程师必须得掌握HTML.CSS和JavaScript. 只懂其中一个或两个还不行,你必须对这三门语言都很熟悉.也不是说必须对这三门语言都非常精通,但你至少要能够运用它们完成大多数 ...

  9. Web前端开发是做什么的?学Web前端有前途吗?

    尚学堂导读 某学员: "前几年前端开发人员鱼目混杂,技术参差不齐,相对学习起来不规范,导致前端开发人员聚集,所以现在前端工种和工资还是没得到普遍重视,但近2年来,HTML5.JS 的流行,让 ...

最新文章

  1. iOS开发 BLE 蓝牙4.0
  2. linux ssh连接交换机_java通过ssh协议管理交换机,linux
  3. python3是unicode还是utf-8_ASCII、Unicode、UTF-8以及Python3编码问题
  4. 关于压缩工具 7z(7-zip) 如何设置压缩算法(选项 -m 的解读)
  5. 3dmax镜像后模型线条乱了_3dMax入门教程来啦!小白赶紧收藏!
  6. arm体系结构与编程_RISCV中文版面市! MIPS、ARM、RISCV三驾马车配齐,奔向体系结构教学的新黄金时代!...
  7. 信息学奥赛一本通C++语言——1054:三角形判断
  8. python生成exe启动很慢,win2000上的python启动非常慢
  9. 基于MVC的jpetstore项目分析
  10. IT职场人生系列之三:第一份工作
  11. 拓端tecdat|matlab从ECG信号数据趋势项的消除
  12. 基于MATLAB语音分析处理系统
  13. 一个简单的HTML网页——传统节日春节网页(HTML+CSS)
  14. maxscale mysql_安装maxscale MySql读写分离
  15. HTML基础-跟着李南江学编程
  16. K线技术指标实现详解—ENE
  17. 计算机用固态硬盘无法启动不了,windows10系统安装固态硬盘开启AHCI后开不了机怎么办...
  18. [转] 记住亦舒的话
  19. WebGis——Pixi开发vue项目之创建pixi应用并显示一个精灵(一)
  20. 游戏程序必备spyder程序--可进可退的多级菜单系统

热门文章

  1. 手握千亿美金的孙正义,这次真的不能如愿了
  2. 《机器学习(周志华)》 习题5.5答案
  3. 柳岩清晨晒素颜照称拿去辟邪 网友称吓人没认出来
  4. moos-ivp使用(一)
  5. 从一到无穷大 #2 优雅的感知与处理Elephant Flows
  6. win32进程共享内存
  7. iPhone和Android的WEB应用开发详解
  8. 烽火通信科技股份有限公司
  9. 行驶证OCR识别应用领域有哪些?
  10. spice-gtk的spicy命令源码分析