С момента рождения языка Go он продолжал разрушать территорию языков Java, C и C++. Во второй половине этого года язык Go выпустил версию 1.11, которая представила технологию WebAssembly, и монополия Javascript на стороне браузера стала подвергаться атаке со стороны языка Go. На этот раз все по-другому, это значит, что язык Go проник из бэкенда во фронтенд, в совершенно новый мир.
Как работает WebAssembly
Название WebAssembly переводится как «Веб-сборка», что является языком ассемблера на стороне Интернета. Это двоичная программа байт-кода.Javascript может скомпилировать эту двоичную программу в модуль, а затем создать экземпляр модуля для вызова логики байт-кода. Код WebAssembly работает очень быстро, намного быстрее, чем Javascript.Javascript может значительно повысить производительность на стороне браузера, передавая ключевую логику, требующую производительности, в WebAssembly через технологию WebAssembly.
Сравнение показывает, что использование WebAssembly для запуска последовательности Фибоначчи может повысить эффективность работы в 3,5 раза по сравнению с использованием собственного Javascript.
WebAssembly — относительно новая технология, и только современные браузеры поддерживают WebAssembly, например браузеры Chrome и FireFox.
Как работает Go WebAssembly
Компилятор Go может компилировать код в двоичный байт-код WebAssembly, который загружается браузером как статический ресурс и преобразуется в модуль Javascript. С помощью этого модуля браузер может напрямую манипулировать логикой двоичного байт-кода, сгенерированной языком Go. В то же время код, написанный на языке Go, может напрямую читать и записывать исполняемый объект Javascript в браузере, тем самым завершая двустороннее взаимодействие между Javascript и кодом Go.
Язык Go не поддерживал WebAssembly до версии 1.11. Для получения опыта необходимо обновиться.
Go WebAssembly первый опыт
Давайте начнем испытывать, как браузер Chrome взаимодействует с кодом Go. Мы хотим реализовать функцию, ввести положительное целое число в поле ввода браузера, затем вызвать последовательность Фибоначчи кода Go, а затем отобразить результат на странице. Задействованы четыре файла, а именно fib.go, main.go, index.html и wasm_exec.js.
первый шаг
Используйте код Go для написания файла модуля WebAssembly fib.go и регистрации функции Фибоначчи, реализованной на языке Go, в глобальной среде Javascript. Для этого необходимо использовать встроенный модуль syscall/js, который предоставляет интерфейс для взаимодействия с движком Javascript.
// fib.go
package main
import "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] = 0
result[1] = 1
if 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, вызвав «пропущенную функцию обратного вызова». Обратите внимание, что основная функция должна оставаться запущенной и не завершаться, иначе зарегистрированное тело функции fib будет уничтожено.
второй шаг
Давайте скомпилируем код Go в двоичный байт-код WebAssembly.
$ GOARCH=wasm GOOS=js go build -o fib.wasm fib.go
После завершения выполнения вы можете увидеть, что в каталоге есть дополнительный файл fib.wasm, который является файлом байт-кода. Его размер составляет 1,3 МБ, что кажется немного большим для передачи в браузер в виде статического файла, но статический файловый сервер обычно имеет сжатие gzip, а сжатый размер составляет всего несколько сотен К, что почти приемлемо.
третий шаг
Напишите файл веб-страницы index.html, эта веб-страница содержит два поля ввода, первое поле ввода используется для ввода целочисленных параметров, а второе поле ввода используется для представления результата расчета. Когда содержимое первого поля ввода изменяется, вызывается код javascript для выполнения функции fib, зарегистрированной в WebAssembly. Функция, которая должна передать аргумент 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, который можно найти в подкаталоге misc установочного каталога Go и скопировать напрямую. В нем реализована функция взаимодействия с модулями WebAssembly.
четвертый шаг
Для запуска статического файлового сервера здесь нельзя использовать обычный статический файловый сервер, поскольку браузер требует, чтобы Content-Type запрашиваемого файла байт-кода WebAssembly был application/wasm, а многие статические файловые серверы не смогут использовать wasm потому что расширение This Content-Type используется автоматически. Но встроенный в Go HTTP-сервер может. Итак, давайте просто напишем статический файловый сервер, используя код Go.
package main
import (
"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/Elliot для…Платформа Go WebAssembly позволяет писать интерфейсные приложения с использованием языка Go. Но я присмотрелся к его исходникам и обнаружил, что это всего лишь игрушка ^_^, в реализации всего несколько строчек кода, а отставание от реального приложения слишком далеко.
Если Go WebAssembly представляет угрозу для javascript, то javascript угрожает не только язык Go.Существуют десятки языков, которые могут компилировать код в байт-код WebAssembly.
Хотите заменить часть кода текущего проекта javascript языком Go, стоимость также очевидна. Необходимо учитывать стоимость переключения стека технологий, стоимость загрузки байт-кода и стоимость непрерывной интеграции фреймворков. Если вы не получите огромного прироста производительности, использование чистого javascript для вашего проекта по-прежнему будет лучшим вариантом.
WeChat ищет «кодовую дыру», следите за публичной учетной записью «кодовая дыра»