整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          「GCTT 出品」Go 和 WebAssembly-

          「GCTT 出品」Go 和 WebAssembly: 在瀏覽器中運行 Go 程序

          長一段時間以來,Javascript 是在 Web 開發者中的通用語言。如果你想寫出一個穩定、成熟的 Web 應用程序,那么使用 Javascript 幾乎是唯一的方法。

          WebAssembly(也叫 wasm )即將改變這種情況。使用 WebAssembly,現在可以用任何語言來編寫 Web 應用程序。在這篇文章當中,我們將明白怎樣編寫 Go 程序并使用 wasm 在瀏覽器中運行它們。

          首先,什么是 WebAssembly

          WebAssembly 官方網站 webassembly.org 對它的定義是“一個基于堆棧的二進制指令格式的虛擬機”。這是一個很好的定義,但是讓我們來將它分解為我們能夠簡單理解的內容。

          從本質上講,wasm 是一種二進制格式,就像 ELF、Mach 和 PE 一樣。唯一的區別是它適用于虛擬編譯目標,而不是真正的物理機。為什么是虛擬機?因為與 C/C++ 的二進制不一樣,wasm 二進制不針對于特定平臺。因此,你可以不用改變任何東西而在 Linux、Windows 和 Mac 上使用同一份二進制文件。但是,我們需要額外的“代理”,它將 wasm 指令中的二進制文件轉換為特定平臺的指令并運行它們。通常,這個“代理”就是一個 Web 瀏覽器,但是理論上講,它可以是任何其它東西。

          這為我們提供了一個通用的編譯目標,我們可以使用自己選擇的任何編程語言來構建 Web 應用程序。只要我們將程序編譯為 wasm 格式,我們就不用擔心目標平臺。就像我們編寫一個 Web 應用程序,但現在我們可以使用我們選擇的任何語言編寫它。

          Hello WASM

          讓我們嘗試從編寫一個簡單的“ hello world ”程序開始。確保你的 Go 版本至少為 1.11。我們可以這樣寫:

          保存為一個 test.go 文件。這看上去就是一個常規的 Go 程序。現在讓我們來編譯這個文件到 wasm 平臺。我們需要像下面這樣設置 GOOS 和 GOARCH 來編譯它。

          $GOOS=js GOARCH=wasm Go build -o test.wasm test.go
          

          我們現在就生成了 wasm 二進制文件。但是與本機系統不同,我們需要在瀏覽器中運行它。為此,我們需要投入一些額外的東西來實現這一個目標:

          • 一個將為我們 Web 應用程序提供服務的 Webserver
          • 一個 index.html 文件,包含一些用于加載 wasm 二進制文件的 JS 代碼
          • 一個 JS 文件,用于作為瀏覽器和我們的 wasm 二進制文件之間的通信接口

          我喜歡把它想象成制作飛天小女警所需要的東西。

          然后 BOOM,我們就有了一個 WebAssembly 應用程序!

          我們已經在 Go 發行版本中提供了 HTML 和 JS 文件,在此我們將它們復制下來。

          serve 是一個簡單的 Go 二進制文件,它為當前目錄中的所有文件提供服務。但是幾乎所有的 Web 服務器都會這樣做。

          一旦我們運行它,并打開我們的瀏覽器。我們看到一個 Run 按鈕,點擊它,將執行我們的應用程序。然后我們點擊它并檢查控制臺:

          優美!我們剛剛使用 Go 編寫了一個程序并在瀏覽器中運行了它。

          到現在為止還挺好。但這是一個簡單的“ hello world ”程序。一個現實世界中的 Web 應用程序需要與 DOM 進行交互。我們需要對按鈕點擊事件進行響應,從文本框中獲取數據,并將數據發送回 DOM。現在我們將構建一個最小的圖片編輯器,這個示例將用到所有的這些功能。

          DOM API

          首先,為了讓 Go 代碼與瀏覽器進行交互,我們需要一個 DOM API。我們需要 syscall/js 庫來幫助我們解決這個問題。它是一個非常基礎但卻強大的 DOM API,我們在其上構建我們的應用程序。在我們轉向制作我們的應用程序之前,讓我們快速了解它的一些功能。

          回調

          為了響應 DOM 事件,我們聲明了回調并用這樣的事件將它們連接起來:

          更新 DOM

          要從 Go 內部更新 DOM,我們可以這樣做 -

          你甚至可以調用 JS 函數和操作本地原生 JS 對象,就像 FileReader 或 Canvas 一樣。請隨時查看 syscall/js 文檔以獲取更多詳細的信息。

          好了,現在開始構建我們的應用程序!

          一個像樣的 Web 應用

          我們將構建一個小的應用程序,它將獲取一個圖片輸入,然后對圖片進行一個操作,如亮度、對比度、色調、飽和度,最后將圖片輸出回瀏覽器中。每一個效果都將會用滑塊,用戶可以更改這些效果并實時查看目標圖像的變化。

          首先,我們需要從瀏覽器獲取輸入圖片到我們的 Go 代碼中,以便我們可以處理它。為了有效的做到這一點,我們需要采取一些 unsafe技巧,具體細節跳過。一旦我們獲取到了圖片,它就完全在我們的掌控之下了,我們就可以隨心所欲的做任何事情。下面是圖片加載器回調的簡短片段,為簡潔起見略有優化:

          然后我們從任何效果滑塊中獲取用戶的值,并操縱圖片。我們使用很棒的 bild 庫。這是操作對比度回調的一小部分片段:

          在此之后,我們將圖片編碼為 jpeg 格式并將其發送回瀏覽器。這是完整的應用程序操作:

          我們加載圖片:

          改變對比度:

          改變色調:

          太棒了,我們可以在瀏覽器中本地操作圖片而不需要編寫一行 Javascript 代碼!可以在 這里 找到源碼。https://github.com/agnivade/shimmer

          請注意,所有這些都是在瀏覽器本身中完成的。這里沒有 Flash 插件、JavaApplets 或 Silverlight。開箱即用的瀏覽器本身對 WebAssembly 提供了支持。

          最后說兩句

          我的一些結束語:

          • 由于 Go 是一門垃圾回收的語言,因此整個運行周期都是在 wasm 二進制文件當中。正因為如此,這些二進制文件通常是 MB 級別的大小。與 C/Rust 語言相比,這是一個痛點;因為向瀏覽器發送 MB 級別的數據是不理想的。然而,要是 wasm 規范本身支持 GC,那么這可能會改變。
          • 在 Go 中對 wasm 進行支持官方在進行試驗。syscall/js API 本身是在不斷變化,將在可能還會變。如果你發現一個 bug,請在我們的 issue tracker 上提出 issue。
          • 與所有集數一樣,WebAssembly 也不是一顆銀彈。有時,簡單的 JS 更快更容易編寫。然而,wasm 本身正在開發中,并將推出更多的功能。線程支持就是這樣一個特性。

          希望這篇文章展示了 WebAssembly 一些很酷的方面,以及如何使用 Go 編寫一個功能齊全的 Web 應用程序。如果你發現一個 bug,請嘗試解決一下,并提出 issue。如果您需要任何幫助,請隨時訪問 #webassembly 頻道。


          via: https://blog.gopheracademy.com/advent-2018/go-in-the-browser/

          作者:Agniva De Sarker 譯者:PotoYang 校對:polaris1119

          本文由 GCTT 原創編譯,Go語言中文網 榮譽推出

          • 本文由 GCTT 原創翻譯,Go語言中文網 首發。
          • 翻譯工作和譯文發表僅用于學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯系我們。
          • 歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在正文中標注并保留原文/譯文鏈接和作者/譯者等信息。
          • 文章僅代表作者的知識和看法,如有不同觀點,請評論排隊吐槽

          「入群交流:Go中文網 QQ群:731990104 微信群:274768166 備注:頭條 微信公眾號:Go語言中文網」

          o語言中文網,致力于每日分享編碼、開源等知識,歡迎關注我,會有意想不到的收獲!

          以常規方式編寫并發程序,需要對共享變量作正確的訪問控制,處理起來很困難。而golang提出一種不同的方式,即共享變量通過channel傳遞,共享變量從不被各個獨立運行的線程(goroutine)同時享有,在任一時刻,共享變量僅可被一個goroutine訪問。所以,不會產生數據競爭。并發編程,golang鼓勵以此種方式進行思考,精簡為一句口號——“勿通過共享內存來進行通信,而應通過通信來進行內存共享”。

          1 Unbuffered channels與Buffered channels

          Unbuffered channels的接收者阻塞直至收到消息,發送者阻塞直至接收者接收到消息,該機制可用于兩個goroutine的狀態同步。Buffered channels在緩沖區未滿時,發送者僅在值拷貝到緩沖區之前是阻塞的,而在緩沖區已滿時,發送者會阻塞,直至接收者取走了消息,緩沖區有了空余。

          1.1 Unbuffered channels

          如下代碼使用Unbuffered channel作同步控制。給定一個整型數組,在主routine啟動另一個goroutine將該數組排序,當其完成時,給done channel發送完成消息,主routine會一直等待直至排序完成,打印結果。

          1.2 Buffered channels

          如下代碼中,messages chan的緩沖區大小為2,因其為Buffered channel,所以消息發送與接收無須分開到兩個并發的goroutine中。

          2 配套使用

          2.1 指明channel direction

          函數封裝時,對僅作消息接收或僅作消息發送的chan標識direction可以借用編譯器檢查增強類型使用安全。如下代碼中,ping函數中pings chan僅用來接收消息,所以參數列表中將其標識為接收者。pong函數中,pings chan僅用來發送消息,pongs chan僅用來接收消息,所以參數列表中二者分別標識為發送者與接收者。

          2.2 select

          使用select可以用來等待多個channel的消息,如下代碼,創建兩個chan,啟動兩個goroutine耗費不等時間計算結果,主routine監聽消息,使用兩次select,第一次接收到了ch2的消息,第二次接收到了ch1的消息,用時2.000521146s。

          2.3 select with default

          select with default可以用來處理非阻塞式消息發送、接收及多路選擇。如下代碼中,第一個select為非阻塞式消息接收,若收到消息,則落入<-messages case,否則落入default。第二個select為非阻塞式消息發送,與非阻塞式消息接收類似,因messages chan為Unbuffered channel且無異步消息接收者,因此落入default case。第三個select為多路非阻塞式消息接收。

          2.4 close

          當無需再給channel發送消息時,可將其close。如下代碼中,創建一個Buffered channel,首先啟動一個異步goroutine循環消費消息,然后主routine完成消息發送后關閉chan,消費goroutine檢測到chan關閉后,退出循環。

          2.5 for range

          for range語法不僅可對基礎數據結構(slice、map等)作迭代,還可對channel作消息接收迭代。如下代碼中,給messages chan發送兩條消息后將其關閉,然后迭代messages chan打印消息。

          3 應用場景

          3.1 超時控制

          資源訪問、網絡請求等場景作超時控制是非常必要的,可以使用channel結合select來實現。如下代碼,對常規sum函數增加超時限制,sumWithTimeout函數中,select的v :=<-rlt在等待計算結果,若在時限范圍內計算完成,則正常返回計算結果,若超過時限則落入<-time.After(timeout) case,拋出timeout error。

          本文代碼托管地址:https://github.com/olzhy/go-excercises/tree/master/channels

          參考資料

          [1] https://golang.org/doc/effective_go.html#channels

          [2] https://gobyexample.com/channel-synchronization

          [3] https://gobyexample.com/channel-buffering

          [4] https://gobyexample.com/channel-directions

          [5] https://gobyexample.com/select

          [6] https://gobyexample.com/non-blocking-channel-operations

          [7] https://gobyexample.com/closing-channels

          [8] https://gobyexample.com/range-over-channels

          [9] https://gobyexample.com/timeouts

          原文:https://leileiluoluo.com/posts/golang-channels.html

          本文作者:磊磊落落的博客,原創授權發布

          018 年接近尾聲,InfoQ 策劃了“解讀 2018”年終技術盤點系列文章,希望能夠給讀者清晰地梳理出重要技術領域在這一年來的發展和變化。本篇文章是 Go 語言 2018 年終盤點,分為上下兩篇。客觀、深入分析 2018 年 Go 語言的技術發展現狀,同時對明年可能的發展情況進行預測和展望。

          今年真可謂是不平靜的一年,前有人工智能國家級戰略的發布,行業已經在大跨步的挺進,但人才缺口每天都在擴大;后有區塊鏈技術從爆發式增長到大幅回落,無數程序員蜂擁而至,又在現如今變得手足無措。

          那么,Go 語言在 2018 年這一年發展得又如何呢?它的下一步又將會怎樣?且聽筆者細細道來。(如果大家還希望了解更多詳情,還可以看下筆者在極客時間的Go 語言專欄)

          首先,筆者要說的是,在 TIOBE 于 2018 年 11 月份公布的編程語言排行榜中,Go 語言已然擠到了前 10 的位置。雖然這與去年同期的第 14 位看起來相差不大,但卻是一個里程碑式的進步。


          圖 1:TIOBE Index for Nov 2018

          從 Google Trends 提供的流行趨勢統計來看,在過去的 12 個月里,Go 語言的流行也是持續升溫的。


          圖 2: Google Trends - Golang 熱度隨時間變化的趨勢

          這種升溫雖然并不算快,但是很持久。這對編程語言的生態環境和人才的發展是非常有利的。

          此外,完全不出乎我們的意料:中國依然是 Go 語言愛好者最多的國家,沒有之一。


          圖 3: Google Trends - Golang 按區域顯示的搜索熱度

          具有諷刺意味的是,作為 Go 語言誕生地的美國,僅排在了第 15 位。我們對先進技術和前沿科技的熱衷絕對是不輸他國的。下面,讓我們再把尺度縮小到城市級別。


          圖 4 :Google Trends - Golang 按區域顯示的搜索熱度(城市)

          顯然,在我國,北京、深圳、上海這三個城市聚集了非常多的 Go 語言程序員和工程師。尤其是北京,簡直是 Go 語言愛好者的圣地啊!

          至于北京博得頭籌的原因,據筆者觀察,首先肯定是:在北京的互聯網公司很多,起碼明顯多于其他的一、二線城市。Go 語言如今在互聯網公司中非常流行,即使有的公司高層并沒有批準大規模地使用 Go 語言,但是工程師們都在做積極的嘗試。

          其次,北京做云計算的公司很多,不論是面向市場的公有云還是自建自用的私有云。說到云計算,我們就不得不提及開放平臺技術、容器技術、集群管理技術,以及現在很火熱的微服務(Microservices)和 Serverless 技術,等等。而這些,恰恰都是 Go 語言的專長。在這些方面,有很多成熟的基于 Go 語言的解決方案可供選擇。

          再次,北京的高科技創業公司非常多。他們往往沒有歷史包袱、勇于創造和嘗試。在做技術選型的時候,他們也更容易選擇 Go 語言。因為,Go 語言既擁有編譯型編程語言固有的高運行效率,又具有解釋型編程語言常有的高開發效率。而且,Go 語言還不像有些編程語言那樣時不時地出現內斗、分裂等混亂情況,當然也沒有無良的技術持有者吵鬧著要對編程語言的商用進行收費。

          Go 語言在語言規范的發展、版本的迭代和開發者生態的建設方面都非常的穩定,并有著良好的包容性和兼容性。保持簡單、面向契約和利于協作是 Go 語言最突出的設計哲學。無論是做軟件原型,還是用于小團隊作戰,又或是進行大規模的研發,Go 語言都會是很不錯的選擇。

          最后,很多喜愛 Go 語言、致力于推廣 Go 語言技術的個人開發者、技術團隊、互聯網公司以及知識服務廠商也都在北京。這都直接或間接地導致了 Go 語言在這座城市的流行。

          好了,到這里,筆者相信你已經對 Go 語言在中國的流行有了一定的了解。下面,我們再來說說 Go 語言在 2018 年具體都有哪些進展。

          首先說一下,關于 Go 語言在 2018 年之前的具體進展,筆者推薦你去看這幾篇同系列文章,如下:

          • 解讀 2015 之 Golang 篇:Golang 的全迸發時代
          • 解讀 2016 之 Golang 篇:極速提升,逐步超越
          • Go 語言的 2017 年終總結

          語法和平臺

          Go 語言官方團隊在 2018 年 2 月正式發布它的 1.10 版本。不同于其他很多被稱為版本帝的編程語言,到了這樣一個版本號 10,Go 1 在語言規范方面已經幾乎沒有什么改動了,一些語法上的小小增強也并不值得我們特別關注。而在 2018 年 8 月發布的 Go 1.11 更是沒有任何語言規范方面的變動。

          Go 語言對于本身的向后兼容性保持得非常好,高版本對低版本中的語言語法、工具和標準庫都不會有任何破壞。然而,Go 語言在其支持的操作系統方面還是很大刀闊斧的。這體現在,Go 1.10 不再支持 10.3 以下版本的 FreeBSD 和 8.0 以下版本的 NetBSD。并且,這個版本也是支持 OpenBSD 6.0、OS X 10.9 以及 Windows XP 和 Windows Vista 的最后一個版本。** 在這些操作系統之上編寫或運行 Go 語言程序的開發者們要注意。

          環境和工具

          使用過 Go 語言的開發者們都知道,當把 Go 語言的預編譯包解壓到某個目錄后,我們還需要至少設置兩個環境變量——GOROOT 和 GOPATH。前者代表直接包含 Go 語言本身的那個目錄路徑,而后者則用于指定可放置第三方庫和自有代碼的工作區(或者說工作目錄)的路徑。

          一個好消息是,自 Go 語言的 1.10 版本起,GOROOT 這個環境變量就沒有必要設置了。如果我們不設置它,那么 Go 的標準工具會嘗試以自身所在的目錄為基礎,自動地推斷出 GOROOT 應該指向的目錄路徑。

          另外,從這個版本開始,我們可以自行地設定 Go 語言的臨時目錄路徑了,設定的途徑是設置環境變量 GOTMPDIR。Go 語言的臨時目錄主要用于存放 Go 工具在編譯或測試程序時產生的各種臨時文件。在這之前,這些臨時文件都會被存放到固定的地方,此地的具體路徑會根據操作系統的不同而不同,一般會位于操作系統的臨時目錄的某個子目錄下。自定義這個目錄的好處在于,可以讓我們方便地觀察編譯過程,并查看編譯或測試的中間結果。

          說到編譯,筆者一定要提一下 1.10 版本的另一項改進,這與 go build 命令有關。以前,如果我們要強行地重新構建所有相關的代碼包,那么就需要在運行這個命令的時候追加標記“-a”。而現在,我們無需這樣做了。go build 命令會根據源碼文件內容、構建標記和編譯元數據,自動地決定什么時候應該重新構建那些代碼包。這項工作再也不需要人工干預了。

          與此項改進相關的變化是,go build 命令現在總是會把最近的構建結果緩存起來,以便在將來的構建中重用。我們可以通過運行 go env GOCACHE 命令來查看緩存目錄的路徑。緩存的數據總是能夠正確地反映出當時的源碼文件、構建環境和編譯器選項等的真實情況。一旦有任何變動,緩存數據就會失效,go build 命令就會再次真正地執行構建。因此,我們并不用擔心緩存數據體現的不是實時的結果。實際上,這正是上述改進能夠有效的主要原因。go build 命令會定期地刪除最近未使用的緩存數據,但如果你想手動刪除所有的緩存數據,運行一下 go clean -cache 命令就好了。

          順便說一下,對于測試成功的結果,go 命令也是會緩存的。運行 go clean -testcache 命令將會刪除掉所有的測試結果緩存。不過別擔心,這樣做肯定不會刪除任何的構建結果緩存,它們是兩碼事。

          此外,設置環境變量 GODEBUG 的值也可以稍稍地改變 go 命令的緩存行為。比如,設置值為 gocacheverify=1 將會導致 go 命令繞過任何的緩存數據,而真正地執行操作并重新生成所有結果,然后再去檢查新的結果與現有的緩存數據是否一致。

          再來說 go install 命令。現在,go install 命令在默認情況下只會去安裝我們明確指定的那些代碼包。這些代碼包依賴的那些包并不會被安裝。這同樣得益于構建結果緩存,它可以使安裝的速度得到明顯的提升。如果你想要強制地安裝依賴包,那么請在運行命令的時候追加“-i”標記。

          程序測試

          前面我們說過了,測試成功的結果也會被緩存。如果 go test 命令確定可以使用被緩存的結果,那么它打印出的內容也會出自于緩存。這時,被打印的內容中會包含“(cached)”字樣。

          另外,go test 命令現在會自動地運行 go vet 命令,以便在真正運行測試之前識別出一些程序編寫方面的問題。我們都知道,go vet 命令用于對 Go 語言源碼進行靜態檢查,并報告已發現的可疑問題。這些問題一般都是符合語法規則的,因此編譯器無法查出它們。但是,它們很有可能代表了對某些程序實體(或者說 API)的錯誤使用。雖然 go vet 命令有時候并不能保證它報告的每一個問題都是真正的問題,但它卻可以給予我們一份重要的參考,以便讓我們在編程的過程中小心行事。

          與 Go 語言提供的很多高級功能一樣,我們也可以阻止 go test 命令自動運行 go vet 命令,這需要在運行前者的時候追加“-vet=off”這個標記。

          最后,關于 go test 命令,還有兩個值得注意的新標記——“-failfast”和“-json”。顧名思義,“-failfast”標記可以讓 go test 命令一旦發現有測試失敗的情況就立即忽略掉剩余的測試并終止運行。不過要注意,如果存在與失敗的測試并發進行的測試的話,那么后者還是會繼續運行直至完成的。“-json”標記對于程序測試的自動化大有裨益。它會讓 go test 命令產生 JSON 格式的測試報告,這使得其他程序很容易讀入和處理。

          程序文檔

          關于程序文檔,只有一點需要我們注意。**Go 1.11 是 godoc 命令支持命令行接口的最后一個版本。** 在未來的版本中,我們運行 godoc 命令的時候,它會啟動一個 Web 服務器,以便讓我們直接進入圖形化界面進行文檔查詢。

          程序性能分析

          現在,runtime/pprof 代碼包中的 Lookup 函數已經支持了更加多樣的參數值。這就意味著,Go 語言的程序性能分析現在可以生成和解讀更多視角下的分析報告了。我們可以把這樣的分析報告包含的內容叫做程序性能概要信息(簡稱概要信息),并把存儲這些分析報告的文件叫做概要文件。

          Lookup 函數可以生成的概要信息目前共有 6 種。這 6 種概要信息分別由字符串類型的參數值goroutine、heap、allocs、threadcreate、block和mutex代表。下面是它們代表的含義:

          • goroutine:收集當前正在使用的所有 goroutine 的堆棧跟蹤信息。
          • heap:收集與堆內存的分配和釋放有關的采樣信息,默認以在用空間(inuse_space)的視角呈現。
          • allocs:同樣收集與堆內存的分配和釋放有關的采樣信息,但默認以已分配空間(alloc_space)的視角呈現。
          • threadcreate:收集一些特定的堆棧跟蹤信息,其中的調用鏈上的代碼都導致了新的操作系統線程的產生。
          • block:收集因爭用同步原語而被阻塞的那些代碼的堆棧跟蹤信息。
          • mutex:曾經作為同步原語持有者的那些代碼的堆棧跟蹤信息。

          這里所說的同步原語,指的是存在于 Go 語言運行時系統內部的一種底層同步工具,或者說一種同步機制。它是直接面向內存地址的,并以異步信號量和原子操作作為實現手段。我們已經熟知的通道、互斥鎖、條件變量、“WaitGroup”以及 Go 語言運行時系統本身,都會利用它來實現自己的功能。

          另外,在用空間和已分配空間的區別是,前者指的是已經分配但還沒有被回收的空間,而后者只關注分配出的空間,不論它們是否已經被回收。

          注意,如果我們在運行 go test 命令的時候追加了標記“-memprofile”,那么該命令會通過底層的 API 以allocs為視角生成概要信息和概要文件。這相當于對從測試開始時的所有已分配字節進行記錄,包含已經被垃圾回收器收回的那些字節。在 Go 1.11 版本之前,go test 命令在這種情況下采用的是heap視角。

          最后,go tool pprof 工具已經可以正確地單獨讀取和處理所有種類的概要文件了。這得益于,從 Go 1.10 版本開始,block和mutex視角下的概要信息已經完善。在這之前,我們使用 go tool pprof 查閱這兩種概要文件的時候,還不得不同時指定相應程序的二進制文件。

          運行時系統

          需要特別注意,runtime 代碼包中的 LockOSThread 函數和 UnlockOSThread 函數的行為已經發生了變化。我們都知道,前一個函數的功能是將當前的 goroutine 與那一時刻正在承載這個 goroutine 運行的操作系統線程進行綁定。在綁定之后,這個 goroutine 就只能由該操作系統線程運行了,反之,該操作系統線程也只能運行這一個 goroutine 了。顯而易見,runtime. UnlockOSThread 函數的功能是解除上述綁定關系。當然了,這兩個函數都只能作用于它們被調用時所在的那個 goroutine。

          以前,runtime. LockOSThread 函數是冪等的。也就是說,無論我們在同一個 goroutine 中調用了它多少次,都只相當于調用了一次。另一方面,只要我們調用一次 runtime. UnlockOSThread 函數,就總是能夠解除針對于當前 goroutine 的這種綁定。

          但是,從 Go 語言的 1.10 版本開始,在我們想要完全解除綁定的時候,可能就需要調用多次 runtime. UnlockOSThread 函數才能夠實現了。至于具體需要調用多少次完全取決于,當初在同一個 goroutine 中調用 runtime. LockOSThread 函數的次數。換句話說,只有進行相同次數的函數調用,才能讓當前 goroutine 與某個操作系統線程之間的綁定關系完全解除。我們可以把現在的這種對應關系理解為是基于嵌套的,可以想象一下:當初包裝了多少層紙箱,現在就要拆開多少層紙箱。

          其實一直以來,有很多第三方 Go 語言庫的作者都誤以為對于這兩個函數的調用就是基于嵌套關系的。不過無論怎樣,我們現在都應該仔細檢查代碼并小心的應對了。

          筆者認為,如果你確實需要進行這種綁定,那么就應該基于這兩個函數封裝一個數據結構。在這個數據結構中,至少應該包含一個用于記錄調用 runtime. LockOSThread 函數次數的字段,以方便后續的解綁操作。

          在 2018 年,對于 Go 語言的運行時系統來說,我們可以輕易感知到的變化基本上只有這一個。不過,非常多的改進和優化都在悄無聲息的進行著,有的已經完成了,而有的還在進展之中。已完成的改進如:在通常情況下,我們傳遞給 runtime.GOMAXPROCS 函數的參數值已經不再受限了,只要它在 int32 類型可容納的范圍之內就可以。

          標準庫

          在 Go 語言的 1.10 和 1.11 這兩個版本中,官方團隊與社區開發者們一起對標準庫做了大量的改進。可喜可賀,社區開發者對 Go 語言的貢獻次數現在已經超過官方團隊了!

          由于這方面的改進繁多,也由于筆者在新近發布的極客時間專欄《Go 語言核心 36 講》中已經詳細講解了不少,所以這里就不再贅述了。

          兩個新實驗

          我們再來說說 Go 1.11 的兩個新實驗吧,一個是對 WebAssembly 的實驗性支持,另一個是推出由 dep 和 vgo 演化而來的依賴管理機制和新概念 module。

          按照官方的描述,WebAssembly(縮寫為 WASM)是一種二進制指令格式,它針對的是以堆棧為基礎的虛擬機。WASM 有很好的可移植性,以便讓 C++、Golang、Rust 等高級編程語言來操控它,并有能力部署到 Web 程序上。

          用普通話來說,WASM 提供了一種途徑,可以讓我們用后端編程語言直接去編寫 Web 頁面中的邏輯。在 Go 1.11 中,我們可以很輕易地把 Go 語言源碼文件轉換為 WASM 格式的文件,然后在 Web 頁面中通過寥寥幾行 JavaScript 代碼引用這個文件并把其中的邏輯發布到頁面上。WASM 的 1.0 版本現在已經支持了絕大多數的主流網絡瀏覽器,比如:Chrome、Firefox、Safari 等。如果想了解具體的玩法,你可以參看這個 wiki 頁面。

          筆者對 Go 語言官方的這種探索性實驗一直都持贊成的態度,不論是前些年的移動端(Android 和 iOS)方向,還是今年的 Web 端(WASM)方向。不過,筆者依然覺得 Go 語言的優勢在服務端,現在很明顯,而且在可預見的未來也應該是如此。所以,對于這些多端探索,筆者建議大家“保持關注,積極試驗,但不要偏移重心”。

          相比之下,筆者倒是更加看好 Go 語言新放出的依賴管理機制。Go 語言愛好者們都知道,Go 語言在這方面一直是缺失的。雖然目前存在幾個不錯的第三方解決方案,但是沒有一個是可以脫穎而出的,同時官方也一直沒有給出一個統一的標準。

          經過了一段時間的試驗和演化,Go 語言官方的依賴管理機制終于脫胎于 dep 和 vgo。雖然其間存在一些摩擦和風波,但是結果終歸是積極的。

          在 Go 語言新的依賴管理機制中,module 是一個非常重要的概念。簡單來說,module 象征著由某個 Go 語言代碼包以及它依賴的代碼包共同組成的一個獨立單元。這里的 Go 語言代碼包和它依賴的那些代碼包都是版本化的。一個 module 的根目錄下總是直接存有一個名為 go.mod 的文件。這個文件中會包含當前 module 的路徑,以及它依賴的那些 module 的路徑和版本號。如此一來,對于每一個版本的 module,它依賴的所有代碼都會被固化下來。這對于后續的版本管理和 module 重建來說都是重要的基礎。詳情可以參看這里的 wiki 頁面。

          不過,不要忘了,Go 1.11 中包含的這個依賴管理機制是實驗性的。其中的任何部分都有可能由于社區的反饋和官方的改進而變化。所以,你在正式使用它之前一定要考慮到后續可能存在的變更成本。雖然如此,筆者仍然會鼓勵廣大開發者們去積極使用和反饋。想象一下 maven 對于 Java 世界的重要性吧。筆者相信,我們心目中的 Go 項目依賴管理機制已經離此不遠了。

          參考文獻

          [1] Go 1.10 is released: https://blog.golang.org/go1.10

          [2] Go 1.11 is released: https://blog.golang.org/go1.11

          [3] Diagnostics: https://golang.google.cn/doc/diagnostics.html

          [4] WebAssembly: https://github.com/golang/go/wiki/WebAssembly

          [5] Modules: https://github.com/golang/go/wiki/Modules

          [6] Go 1.12 Release Notes(DRAFT): https://tip.golang.org/doc/go1.12

          [7] Nine years of Go: https://blog.golang.org/9years

          [8] Toward Go 2: https://blog.golang.org/toward-go2

          [9] Go 2 Draft Designs: https://go.googlesource.com/proposal/+/master/design/go2draft.md


          作者簡介郝林,國內知名的 Go 語言技術布道者,GoHackers 技術社群的發起人和組織者。他也是極客時間專欄《Go 語言核心 36 講》的作者,以及圖靈原創圖書《Go 并發編程實戰》的作者。他曾在輕松籌任大數據負責人,同時負責大數據部門和主站的后端技術團隊。

          主站蜘蛛池模板: 国产在线步兵一区二区三区| 国产一区二区三区四| 内射女校花一区二区三区| 无码一区二区三区| 成人精品视频一区二区| 亚洲AV无码第一区二区三区| 老鸭窝毛片一区二区三区| 亚洲一区二区三区免费视频| 中文字幕精品亚洲无线码一区应用| 久久无码AV一区二区三区| 中文字幕精品一区| 国产人妖视频一区在线观看| 国产日本一区二区三区| 亚洲AV综合色区无码一区| 亚洲一区二区三区乱码A| 人妻少妇精品视频三区二区一区| 亚洲一区二区三区偷拍女厕| 日本一区二区三区在线观看视频| 亚洲区精品久久一区二区三区| 中文字幕在线观看一区| 国产一区二区精品久久岳√| 精品国产日韩亚洲一区91| 亚洲无码一区二区三区| 精品欧洲av无码一区二区| 日韩精品无码一区二区三区不卡| 红桃AV一区二区三区在线无码AV| 国产一区二区视频免费| 国产日韩综合一区二区性色AV| 亚洲a∨无码一区二区| 无码播放一区二区三区| 精品无码一区二区三区电影| 日本内射精品一区二区视频 | 末成年女AV片一区二区| 国产亚洲一区二区三区在线| 精品无码人妻一区二区三区不卡| 人妻内射一区二区在线视频| 人妻体内射精一区二区| 国产福利电影一区二区三区久久老子无码午夜伦不 | 亚洲av午夜福利精品一区人妖| 激情内射亚州一区二区三区爱妻| 国产A∨国片精品一区二区|