предисловие
Мы знаем, что в нынешнюю эпоху различной контейнеризации Go стал предпочтительным внутренним языком разработки для разработки контейнерных приложений. В настоящее время k8s, самая непрофессиональная контейнерная система управления и оркестрации, используется почти всеми крупными поставщиками облачных услуг. А k8s разработан Google с использованием языка go. Теперь go можно использовать для разработки интерфейсных языков, и есть ощущение, что «каждая функция, которая может быть реализована на языке go, в конечном итоге будет реализована на языке go». Эта статья в основном используется для ознакомления с тем, как начать разработку внешнего интерфейса на языке го.
установка среды разработки go
Во-первых, вам нужно скачать и установить go. ссылка на скачивание:golang.org/Установка на самом деле очень проста, поэтому я не буду говорить об этом здесь.После завершения установки выполните следующую команду в консоли, чтобы убедиться, что установка go прошла успешно.
go version
Если он может нормально выводить, это доказывает, что ваша среда была установлена.Это очень просто?
Почему go можно использовать для фронтенд-разработки
В версии 1.11 в go добавлена поддержка WebAssembly, текущая версия go достигла версии 1.14, можно сказать, что WebAssembly поддерживается очень хорошо. Для получения дополнительной информации о WebAssembly на языке Go вы можете проверить официальную вики:GitHub.com/gowaves/go/me….
Поскольку код, написанный на Go, можно преобразовать в WebAssembly, а WebAssembly — это язык двоичного формата, который может работать в любом современном браузере, Go можно использовать для разработки интерфейсных приложений.
Простая демонстрация для начала
Посмотрите прямо на код:
Например, код вашей html-страницы выглядит следующим образом:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="test">test</button>
</body>
</html>
На странице есть элемент кнопки, идентификатор кнопки «тест».
Давайте посмотрим, как получить этот элемент на языке Go.
package main
import (
"syscall/js"
)
js.Global().Get("document").Call("getElementById", "test")
В приведенном выше коде мы вызываем метод, предоставленный в пакете «syscall/js», для получения объекта документа и вызываем метод документа getElementById для получения элемента кнопки на нашей html-странице. Но тут по сути ничего не видно.После попытки получить элемент кнопки меняем текст кнопки на "changed by go".
btn := js.Global().Get("document").Call("getElementById", "test")
btn.Set("innerHTML", "changed by go")
После написания код, вероятно, будет похож на приведенный выше, а остальные части выкладываться не будут. На данный момент базовая демонстрация написана, так как же ее протестировать?
Во-первых, нам нужно скомпилировать код go в WebAssembly, а затем нам также нужно использовать библиотеку js, предоставленную нам go to, которая используется для вызова сгенерированного WebAssembly, скомпилированного go in js, а затем выполнить логику кода внутри . . .
Во-первых, мы копируем библиотеку js, предоставленную go, в каталог.
Выполните следующую команду в корневом каталоге проекта:
cp $(go env GOROOT)/misc/wasm/wasm_exec.js .
После запуска это выглядит примерно так.
Затем нам нужно скомпилировать код go в формат wasm.
Используйте следующую команду, чтобы скомпилировать код go в формат wasm.
GOOS=js GOARCH=wasm go build -o main.wasm main.go
Здесь необходимо объяснить роль двух переменных среды GOOS и GOARCH. Код на ходу может быть скомпилирован в целевые результаты для каждой платформы. Например, GOOS можно указать как windows или linux. Здесь он также может быть указан как js.
GOARCH представляет системную архитектуру, например, может быть указан как amd64 или 386 и т. д. Здесь он также может быть указан как wasm.
После выполнения вышеуказанной команды мы видим, что в каталоге есть дополнительный файл wasm.
Вот, приготовления почти закончены. Нам нужно представить библиотеку js, предоставленную переходом в html, а затем использовать main.wasm, который мы только что скомпилировали и сгенерировали.
Измените html следующим образом:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="test"></button>
</body>
<script src="./wasm_exec.js"></script>
<script>
const go = new Go()
WebAssembly.instantiateStreaming(fetch('app.wasm'), go.importObject)
.then(result => go.run(result.instance))
</script>
</html>
В вышеупомянутый код WebAssembly NStantiateSteSteSteSteSteSteSteSteSteSteSteSteSteationS и создает интеграцию модуля Webassembly непосредственно из потокового базового источника. Это очень эффективная оптимизация для загрузки WASM-кода.
Излишне говорить, что забрать.
go.importObject
Является объектом, этот объект будет импортирован в модуль wasm, чтобы к объекту js можно было получить доступ в модуле wasm.
Здесь go.importObject выглядит так:
Посмотрите исходный код в библиотеке js, предоставленной go, в ней есть комментарии.
Здесь importObject в основном используется для вызова js-кода в wasm-файле (метод, предоставляемый js, вызывается в wasm-е), а на ходу он в основном используется для работы с изменениями SP (Stack Pointer).
После того, как приведенный выше код готов, мы можем запустить http-сервис, для запуска рекомендуется использовать http-сервер,GitHub.com/HTTP-вечеринка/…
После завершения запуска посетитеhttp://127.0.0.1:8080/
Видно, что после визита наш wasm-файл по-прежнему корректен, и код, который мы написали с помощью go, выполняется, а текст кнопки меняется на «changed by go».
Добавить обработчик события клика на кнопку
В приведенном выше коде мы изменяем текст кнопки только при ее посещении, и нет никакой другой операции Давайте посмотрим, добавим ли мы событие нажатия на кнопку.
Сначала нам нужно объявить функцию, которая будет использоваться в качестве функции обратного вызова для события клика.
func main() {
btn := js.Global().Get("document").Call("getElementById", "test")
callback := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
fmt.Println(this)
fmt.Println(args)
fmt.Println("button clicked")
return nil
})
btn.Set("innerHTML", "changed by go")
btn.Call("addEventListener", "click", callback)
}
В приведенном выше коде сначала создается функция, которая будет вызываться в js, путем вызова FuncOf пакета js. В параметрах FuncOf мы можем видеть определенную функцию обратного вызова. Эта функция имеет два параметра, первый параметр представляет этот объект при вызове js, а второй параметр представляет параметр при вызове.
После добавления приведенного выше кода мы регенерируем wasm-файл, затем обновляем страницу, нажимаем кнопку и смотрим, выводится ли строка «нажата кнопка».
После нажатия кнопки «Готово» я обнаружил, что сообщается об ошибке, указывающей на то, что программа go завершила работу.Почему это?
Глядя на приведенный выше код, мы обнаруживаем, что в основной функции, после выполнения всего кода, основной поток go выходит напрямую, а функция обратного вызова, которую мы создали с помощью js.FuncOf, фактически выполняется в отдельной горутине. поток завершился, горутина не может быть выполнена.
Чтобы исправить эту ошибку, нам нужно убедиться, что основной поток не завершается. Измените код следующим образом:
func main() {
btn := js.Global().Get("document").Call("getElementById", "test")
signal := make(chan int)
var callback js.Func
callback = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
fmt.Println(this)
fmt.Println(args)
fmt.Println("button clicked")
return nil
})
btn.Set("innerHTML", "changed by go")
btn.Call("addEventListener", "click", callback)
<- signal
}
Здесь добавлена переменная типа канала.Чтобы узнать о канале, вы можете проверить официальную документацию или посмотреть заметки о переходе, которые я писал ранее (nuggets.capable/post/684490…
Используемый здесь канал в основном используется для предотвращения выхода основного потока go.В последнем предложении
Взгляните на результат нормального выполнения:
Можно обнаружить, что событие клика, которое мы зарегистрировали для кнопки, может срабатывать нормально, и функция обратного вызова также выполняется нормально.
Если вы внимательно посмотрите на приведенный выше код, вы обнаружите, что использование Go для работы с домом довольно проблематично. Например, каждый раз, когда вы получаете элемент dom, вам нужно:
js.Global().Get("document").Call("getElementById", "test")
Кроме того, мы можем вызывать методы dom только так:
btn.Call("addEventListener", "click", callback)
Имя метода здесь используется как параметр, и легко ошибиться.
Все, некоторые люди в сообществе инкапсулировали эти операции, например:перейдите на doc.org/ или на F.co/…
эта библиотека.
Глядя на документацию, я обнаружил, что она больше соответствует тому, как мы обычно используем js для работы с dom.
Суммировать
В последние годы Go становится все более популярным в Китае, особенно после развития облачных технологий и контейнеризации. Ключевым моментом является то, что Go не только обладает хорошей производительностью, но и занимает очень мало памяти и т. д. В настоящее время большинство новых фоновых проектов также переписывается с использованием Go.
说明:
Поскольку есть комментарии о применимых проблемах, позвольте мне объяснить здесь. Прежде всего, для обычных интерфейсных приложений совершенно необязательно использовать Go для разработки wasm, потому что, возможно, ваш сценарий проекта не требует использования wasm. это, кроме увеличения сложности, не принесло никакой пользы. Но в некоторых особых сценариях, когда вам нужно использовать wasm, в это время вы разрабатываете на Go, что более освежает.
Сценарии использования wasm могут относиться к:
Web Assembly.org.capable/docs/use-wipe…
Блог.лог-rocket.com/web-сборка...
Использованная литература: