日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

可能是世界上最简单的用 Go 来写 WebAssembly 的教程

發布時間:2024/2/28 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 可能是世界上最简单的用 Go 来写 WebAssembly 的教程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原標題:The world’s easiest introduction to WebAssembly???? 原文鏈接:The world’s easiest introduction to WebAssembly - freeCodeCamp.org - Medium? 作者:Martin Olsansky (olso)

一個與貓咪交互的 Canvas 手機游戲,這個項目完全由 Golang 編寫。圖里這只小貓正在體驗我編寫的小游戲
  • 你認為 WebAssembly (WASM) 只用于圖像處理、復雜的數學計算或者 Web 上的小小應用嗎?

  • 你是否經常將 WASM 與 Web Workers 和 Service Workers 的概念混淆?

  • 你對 WASM 不感興趣,是因為你認為現在的 Web 應用程序在未來 10 年里依舊是 JavaScript 主導?

  • 你是否想過用 JS 以外的語言做 Web 前端開發?

如果你不想細讀,你可以看下我做的 demo ?頁面或者直接看下 ???? go-wasm-cat-game-on-canvas-with-docker 這個項目,我會講的簡潔一些,盡量不浪費你的時間。以下是我這個項目的一些關鍵的代碼解析。

故事開始了 ????

我們的目標是給貓 ???? 做一個簡單的小游戲:做一個小紅點在手機上不停的移動,整個過程還有 HiFi 音樂 ????還有震動。整個項目我們會用 ?Golang (Go)這門語言來實現,包括 DOM 操作、邏輯還有相關的狀態。

而且,由于貓咪不會使用鼠標,我們還需要給貓爪 ???? 做一些點擊觸摸的交互。

說一下我的理解!

把 WASM 想象成一個 通用虛擬機(UVM, Universal Virtual Machine) 或者一個沙箱,你只需編寫一次任何代碼,它便可以在任何地方運行。

WASM 是一個編譯目標,而不是一種語言。就像你要同時針對 Windows,Mac OS 和 Linux 進行編譯一樣!

我不認為 WASM 會廢棄 JS,你可以有其他選擇而不用付出任何代價。

想象一下使用 Go,Swift,Rust,Ruby,C ++,OCaml 或者其他語言的開發人員。現在,他們可以使用自己喜歡的語言來創建交互式,聯網,快速,具有脫機功能的網站和Web 應用。

你是否曾經參與過類似「一個項目是用一個代碼倉庫管理還是多個代碼倉庫管理?」問題的討論?

好吧,不管你有沒有,你現在也要想一下現在這個項目打算用一門語言實現還是多門語言實現了。

當大家可以使用相同的技術棧時,一切都會變得更加容易,尤其是團隊之間的溝通。

你可以依舊使用 React 或者 Vue,但你現在開始也可以不用使用 JS 來開發了。

WASM 跟 Service Workers 還有 Web Workers 有什么區別?

Service Workers 還有 Web Workers 允許應用在后臺運行,也可以做到離線運行和緩存。它們模仿線程,無法訪問DOM,并且不能共享數據(僅能通過消息傳遞),只能在單獨的上下文中運行。咦,其實我們甚至可以在其中運行 WASM 而不是 JS。對我來說,它們只提供一些具有特殊特權的抽象層,沒有人說這些層必須執行 JS。

Service Workers 還有 Web Workers 是瀏覽器上的功能,不是 JS 的專有功能。

設置開發環境 ????

我們將使用 WASM,Go,JS 和 Docker(這個是可選的)???? 來進行開發。

如果您不了解Go,但了解 JS,請 點擊這里學習 Go,然后再回來繼續閱讀。讓我們從 Go WASM Wiki 開始。

你可以使用安裝在電腦本地的 ?go 版本,在這里我使用 Docker 的 golang:1.12-rc 鏡像。只需在此處為 go 編譯器設置兩個 WASM 標志。在 main.go 中創建一個簡單的 hello world 進行測試。

$?GOOS=js?GOARCH=wasm?go?build?-o?game.wasm?main.go build_go:docker?run?--rm?\-v?`pwd`/src:/game?\--env?GOOS=js?--env?GOARCH=wasm?\golang:1.12-rc?\/bin/bash?-c?"go?build?-o?/game/game.wasm?/game/main.go;?cp?/usr/local/go/misc/wasm/wasm_exec.js?/game/wasm_exec.js"

現在,讓我們利用好 Go 團隊提供的 wasm_exec.js ?代碼。代碼里的全局變量 Go 對 WASM 進行了初始化操作,我們不必自己從頭開始做好任何 DOM 的實現。等我們編譯好 wasm 文件后,它會獲取 .wasm 文件并運行我們的游戲。

總而言之,它應該看起來像這樣:

<!DOCTYPE?html> <html><head><meta?charset="utf-8"?/><meta?name="viewport"?content="width=device-width,initial-scale=1.0"?/><style>body{height:100%;width:100%;padding:0;margin:0;background-color:#000000;color:#FFFFFF;font-family:Arial,Helvetica,sans-serif}</style><script?type="text/javascript"?src="./wasm_exec.js"></script><script?type="text/javascript">async?function?run(fileUrl)?{try?{const?file?=?await?fetch(fileUrl);const?buffer?=?await?file.arrayBuffer();const?go?=?new?Go();const?{?instance?}?=?await?WebAssembly.instantiate(buffer,?go.importObject);go.run(instance);}?catch?(err)?{console.error(err);}}setTimeout(()?=>?run("./game.wasm"));</script></head><body></body> </html>

放碼過來!(當然是 Go 的碼)

要渲染我們的這個小游戲,<canvas> 這個標簽應該足夠了。我們可以直接從 Go 代碼創建 DOM 結構和元素!這個 syscall/js 文件 (包含在標準 Go 庫中)為我們處理了與 DOM 交互的方法。

main() 方法

我敢打賭,你很久沒見過 main() 方法了????。

package?mainimport?(//?https://github.com/golang/go/tree/master/src/syscall/js"syscall/js" )var?(//?js.Value?可以是任意的?JS?對象、類型或者構造函數window,?doc,?body,?canvas,?laserCtx,?beep?js.ValuewindowSize?struct{?w,?h?float64?} )func?main()?{setup() }func?setup()?{window?=?js.Global()doc?=?window.Get("document")body?=?doc.Get("body")windowSize.h?=?window.Get("innerHeight").Float()windowSize.w?=?window.Get("innerWidth").Float()canvas?=?doc.Call("createElement",?"canvas")canvas.Set("height",?windowSize.h)canvas.Set("width",?windowSize.w)body.Call("appendChild",?canvas)//?這個是小紅點??????Canvas?對象laserCtx?=?canvas.Call("getContext",?"2d")laserCtx.Set("fillStyle",?"red")//?http://www.iandevlin.com/blog/2012/09/html5/html5-media-and-data-uri/beep?=?window.Get("Audio").New("data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU2LjI1LjEwMQAAAAAAAAAAAAAA/+NAwAAAAAAAAAAAAFhpbmcAAAAPAAAAAwAAA3YAlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaW8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDwAAAAAExhdmYAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAN2UrY2LgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/jYMQAEvgiwl9DAAAAO1ALSi19XgYG7wIAAAJOD5R0HygIAmD5+sEHLB94gBAEP8vKAgGP/BwMf+D4Pgh/DAPg+D5//y4f///8QBhMQBgEAfB8HwfAgIAgAHAGCFAj1fYUCZyIbThYFExkefOCo8Y7JxiQ0mGVaHKwwGCtGCUkY9OCugoFQwDKqmHQiUCxRAKOh4MjJFAnTkq6QqFGavRpYUCmMxpZnGXJa0xiJcTGZb1gJjwOJDJgoUJG5QQuDAsypiumkp5TUjrOobR2liwoGBf/X1nChmipnKVtSmMNQDGitG1fT/JhR+gYdCvy36lTrxCVV8Paaz1otLndT2fZuOMp3VpatmVR3LePP/8bSQpmhQZECqWsFeJxoepX9dbfHS13/aysppUblm//8t7p2Ez7xKD/42DE4E5z9pr/nNkRw6bhdiCAZVVSktxunhxhH//4xF+bn4//6//3jEvylMM2K9XmWSn3ah1L2MqVIjmNlJtpQux1n3ajA0ZnFSu5EpXuGatn///1r/pYabq0mKT//TRyTEFNRTMuOTkuNaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq/+MQxNIAAANIAcAAAKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqg==") }

看起來是不是很像 JS 代碼?

是的,這就是與 DOM 交互所需的全部內容!現在只需要幾個 get 方法還有調用函數即可。

awsl???? 它就在那!

在這一點上,我問自己:在某種程度上,我仍然在寫 JS … 這怎么算是升級?因為我們還不能直接訪問 DOM,所以我們必須(通過 JS)調用 DOM 來做任何事情。想象一下如何用 JSX / React 來抽象化它。

實際上,已經可以做到了,請期待我的下篇文章 ????。

「渲染」還有事件處理

直接使用 syscall / js 庫,這個寫法看起來有點像 ES5 的回調。但我們能夠監聽 DOM 事件,而且那些靜態類型看起來很干凈!

func?main()?{setup()//?在編譯時聲明渲染器var?renderer?js.Func//?沒有錯,看起來很像?JS?的回調?????renderer?=?js.FuncOf(func(this?js.Value,?args?[]js.Value)?interface{}?{updateGame()//?實現?60FPS?的動畫window.Call("requestAnimationFrame",?renderer)return?nil})window.Call("requestAnimationFrame",?renderer)//?讓我們處理下?鼠標/手勢?點擊事件var?mouseEventHandler?js.Func?=?js.FuncOf(func(this?js.Value,?args?[]js.Value)?interface{}?{updatePlayer(args[0])return?nil})window.Call("addEventListener",?"pointerdown",?mouseEventHandler) }func?updatePlayer(event?js.Value)?{} func?updateGame()?{}

日志記錄、音頻播放以及「異步」執行

在 Go 中,有一個慣例是把所有的函數都寫成同步的方式,由調用者決定函數的執行是否是異步的。異步運行函數非常簡單,只要在前面加上 go 就行了!它使用自己的上下文創建一個線程,你仍然可以將父級上下文綁定給它,不要擔心哈。

func?updatePlayer(event?js.Value)?{mouseX?:=?event.Get("clientX").Float()mouseY?:=?event.Get("clientY").Float()//?`go`?關鍵字是主要用來實現線程、異步、并行的功能//?TODO?與?Web?Workers?的區別//?TODO?與?Service?Workers?的區別//?https://gobyexample.com/goroutinesgo?log("mouseEvent",?"x",?mouseX,?"y",?mouseY)//?下一個關鍵點if?isLaserCaught(mouseX,?mouseY,?gs.laserX,?gs.laserY)?{go?playSound()} }//?不要以為我用了什么黑魔法,這里直接使用了?HTML5?的?API //?https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement#Basic_usage func?playSound()?{beep.Call("play")window.Get("navigator").Call("vibrate",?300) }//?這里主要用了?JS?的解構賦值語法 //?這里的?`...interface{}`?有點像?TS?的?`any`?語法 //?https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters#Description func?log(args?...interface{})?{window.Get("console").Call("log",?args...) }

讓游戲一直跑下去!

該代碼創建一個非緩沖通道,并嘗試從該通道接收數據。因為沒有人向它發送任何東西,它本質上是一個永久的阻塞操作,允許我們永遠運行我們的程序。

func?main()?{//?https://stackoverflow.com/a/47262117//?創建空通道runGameForever?:=?make(chan?bool)setup()//?嘗試從空通道接收//?由于沒有人向它發送任何數據,它本質上是一個永久阻塞操作//?我們有一個?daeomon?/?service?/?background?程序//?在?WASM?里,我們的游戲會一直運行?????<-runGameForever }

更新游戲狀態并移動小紅點

這里沒有狀態管理,只有一個簡單的聲明類型的結構體,它不允許在內部傳遞任何不正確的值。

import?("math" )type?gameState?struct{?laserX,?laserY,?directionX,?directionY,?laserSize?float64?}var?(//?gs?處于最高范圍,小于這個范圍小紅點??????都能都能訪問gs?=?gameState{laserSize:?35,?directionX:?3.7,?directionY:?-3.7,?laserX:?40,?laserY:?40} )func?updateGame()?{//?邊界判斷if?gs.laserX+gs.directionX?>?windowSize.w-gs.laserSize?||?gs.laserX+gs.directionX?<?gs.laserSize?{gs.directionX?=?-gs.directionX}if?gs.laserY+gs.directionY?>?windowSize.h-gs.laserSize?||?gs.laserY+gs.directionY?<?gs.laserSize?{gs.directionY?=?-gs.directionY}//?移動小紅點?????gs.laserX?+=?gs.directionXgs.laserY?+=?gs.directionY//?清除畫布laserCtx.Call("clearRect",?0,?0,?windowSize.w,?windowSize.h)//畫一個小紅點?????laserCtx.Call("beginPath")laserCtx.Call("arc",?gs.laserX,?gs.laserY,?gs.laserSize,?0,?math.Pi*2,?false)laserCtx.Call("fill")laserCtx.Call("closePath") }//?判斷點擊的點是不是在小紅點??????內部 func?isLaserCaught(mouseX,?mouseY,?laserX,?laserY?float64)?bool?{//?直接這樣返回是不行的//?return?laserCtx.Call("isPointInPath",?mouseX,?mouseY).Bool()//?所以這里我通過勾股定理??????來實現//?同時我給?laserSize?屬性的值加上?15,讓貓爪更容易點擊??????return?(math.Pow(mouseX-laserX,?2)?+?math.Pow(mouseY-laserY,?2))?<?math.Pow(gs.laserSize+15,?2) }

總結

事實上,WASM 仍然被認為是一個 [MVP](https://hacks.mozilla.org/2018/10/webassembly -post- MVP -future/) (MAP),你可以不用編寫一行 JS,就能創建一個像這樣的游戲。驚不驚訝!CanIUse 上 WASM 的支持已經是一片綠色了,沒有人可以阻止你去創建基于 WASM 的網站和應用。

你可以組合所有你想要的語言,像是把 JS 轉成 WASM。最后,它們都將編譯成 WASM 字節碼。如果你需要在他們之間分享任何東西,也沒問題,因為它們可以共享原始內存。

我擔心的是,在最近的新聞中,我們關注到 微軟正在開發 Chromium 瀏覽器 還有 Firefox市場份額低于9%。這使谷歌在 WASM 上有了致命的切換能力。如果他們不愿意配合,大眾可能永遠不會知道有這個特性。

你看這只貓玩的多開心 ????

現在都有誰在用 WASM?

你必須得承認,我的項目已經在用了。這個項目僅僅是畫了一個全屏的畫布,這里有一些更高級的例子,它們關注于語義 Web awesome-wasm#web-frameworks-libraries。

同時,也有相當多的項目已經上了 WASM 的車了。我對 Spotify、Twitch 和 Figma 和 EWASM 更感興趣。

Web3 時代的 WASM

現在,如果你想在手機上使用以太坊錢包(Ethereum wallet),你必須從應用商店下載一個類似于 Status.im 的移動端錢包 App,并且信任所有商家。

如果有一個先進的 Web App,可以運行 geth (Go Ethereum 客戶端),并且能在 WebRTC 上光速同步,這會怎么樣?它可以使用 Service Worker 來更新它的 WASM 代碼并在后臺運行,可以托管在 IPFS/Dat 上。

一些有用的關于 WASM 的文章、資源還有學習資料 ????

  • WebAssembly is more than the web

  • WebAssembly and Go: A look at the future ?還有 ?HN comments

  • Mozilla Hacks ?和 Hacker News 發布的文章

  • WebAssembly architecture for Goawesome-wasm , awesome-wasm-langs , ?gowasm-experiments , ?WasmWeekly , WasmRocks , ?SPA with C++ , ?better DOM bindings for Go

感謝 twifkak 在 Android Chrome 上對 Go 的優化!

總結

以上是生活随笔為你收集整理的可能是世界上最简单的用 Go 来写 WebAssembly 的教程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩精品综合 | 国产高中女学生第一次 | 国产在线观看黄 | 最新福利在线 | 成人丁香婷婷 | 久久中文字 | 欧美日日 | 国产精品欧美综合 | 国产成人三级一区二区在线观看一 | 国产毛片一区二区三区 | 91久久精品一区二区三 | 天堂国产 | 精品国产一区二区三区四区精华 | 亚洲欧美日韩综合一区二区 | 日韩a在线 | 黄色在线资源 | 色婷婷国产精品视频 | 日韩黄色片在线观看 | 久久成人在线观看 | 欧美一区二区三区免费在线观看 | 日韩精品第二页 | 性少妇videosexfre| 蜜臀尤物一区二区三区直播 | 欧美午夜剧场 | 少妇第一次交换又紧又爽 | 潘金莲性xxxxhd | 国产精品视频久久久 | 午夜伦视频 | 国产精品三区四区 | 69xxx国产 | 免费视频一区二区 | 爱久久视频 | 伊人久久网站 | av片一区二区 | 天堂а√在线最新版中文在线 | 91一区在线观看 | 最新国产一区 | 国产在线aaa | 色综合99久久久无码国产精品 | 久久女 | a√在线| 久久久国产精品x99av | 久久久久国产精品夜夜夜夜夜 | 欧美精品久久久久久久久 | 激情www| 自由成熟xxxx色视频 | 人妻视频一区二区 | 日韩经典在线观看 | 日韩欧美超碰 | 97超碰免费 | 日韩av麻豆 | 国产一线二线三线在线观看 | 欧美激情视频在线播放 | 亚洲 小说区 图片区 | 亚洲av无码不卡 | 熟妇高潮喷沈阳45熟妇高潮喷 | 久久人人妻人人人人妻性色av | 米奇狠狠干 | 中文字幕一区二区三区四区视频 | 日韩一区二区三区中文字幕 | 亚洲色图狠狠干 | 男人的天堂视频网站 | 精品久久久久久久久久 | 射影院 | 动漫美女被到爽流 | 蜜桃视频色 | 一区二区在线 | 狼人伊人av | 东京久久久 | 首尔之春在线观看 | 色一情一伦一子一伦一区 | 天天躁日日躁狠狠躁免费麻豆 | 无码乱人伦一区二区亚洲 | 欧洲成人免费视频 | 日韩欧美国产一区二区 | 欧美日韩在线视频观看 | av体验区| 爱的色放3| 国产丝袜视频 | 18岁成年人网站 | 尹人香蕉 | 黄色免费在线播放 | 黄色动漫在线观看 | 啦啦啦视频在线观看 | 成人在线观看小视频 | 欧美一级片网址 | 久久久精品国产sm调教 | 四虎最新站名点击进入 | av在线浏览 | 亚洲三级在线播放 | 成人av免费网址 | 国产日产精品一区 | 黄色大片免费看 | 91精品区| 久久老司机精品视频 | 午夜av网| 秋霞99| 艳妇乳肉豪妇荡乳av无码福利 | 久久久久麻豆v国产精华液好用吗 |