從此再無包下載的任何煩惱:看高手是如何參透 Go Module 的?

2021-02-26 Go語言中文網

點擊上方藍色「Go語言中文網」關注我們,設個星標,每天學習 Go 語言

大家好,我是一隻普通的煎魚,周四晚上很有幸邀請到 goproxy.cn 的作者 @盛傲飛(@aofei) 到 Go 夜讀給我們進行第 61 期 《Go Modules、Go Module Proxy 和 goproxy.cn》的技術分享。

本次 @盛傲飛 的夜讀分享,是對 Go Modules 的一次很好的解讀,比較貼近工程實踐,我必然希望把這塊的知識更多的分享給大家,因此有了今天本篇文章,同時大家也可以多關注 Go 夜讀,每周會通過 zoom 在線直播的方式分享 Go 相關的技術話題,希望對大家有所幫助。

註:本文比較長,建議預留好時間。

前言

Go 1.11 推出的模塊(Modules)為 Go 語言開發者打開了一扇新的大門,理想化的依賴管理解決方案使得 Go 語言朝著計算機編程史上的第一個依賴烏託邦(Deptopia)邁進。隨著模塊一起推出的還有模塊代理協議(Module proxy protocol),通過這個協議我們可以實現 Go 模塊代理(Go module proxy),也就是依賴鏡像。

Go 1.13 的發布為模塊帶來了大量的改進,所以模塊的扶正就是這次 Go 1.13 發布中開發者能直接感覺到的最大變化。而問題在於,Go 1.13 中的 GOPROXY 環境變量擁有了一個在中國大陸無法訪問到的默認值 proxy.golang.org,經過大家在 golang/go#31755 中激烈的討論(有些人甚至將話提上升到了「自由世界」的層次),最終 Go 核心團隊仍然無法為中國開發者提供一個可在中國大陸訪問的官方模塊代理。

為了今後中國的 Go 語言開發者能更好地進行開發,七牛雲推出了非營利性項目 goproxy.cn,其目標是為中國和世界上其他地方的 Gopher 們提供一個免費的、可靠的、持續在線的且經過 CDN 加速的模塊代理。可以預見未來是屬於模塊化的,所以 Go 語言開發者能越早切入模塊就能越早進入未來。

如果說 Go 1.11 和 Go 1.12 時由於模塊的不完善你不願意切入,那麼 Go 1.13 你則可以大膽地開始放心使用。本次分享將討論如何使用模塊和模塊代理,以及在它們的使用中會常遇見的坑,還會講解如何快速搭建自己的私有模塊代理,並簡單地介紹一下七牛雲推出的 goproxy.cn 以及它的出現對於中國 Go 語言開發者來說重要在何處。

目錄

Go Modules 簡介

快速遷移項目至 Go Modules

使用 Go Modules 時常遇見的坑

Go Module Proxy 簡介

Goproxy 中國(goproxy.cn)

Go Modules 簡介

Go modules (前身 vgo) 是 Go team (Russ Cox) 強推的一個理想化類語言級依賴管理解決方案,它是和 Go1.11 一同發布的,在 Go1.13 做了大量的優化和調整,目前已經變得比較不錯,如果你想用 Go modules,但還停留在 1.11/1.12 版本的話,強烈建議升級。

三個關鍵字強推

首先這並不是亂說的,因為 Go modules 確實是被強推出來的,如下:

之前:大家都知道在 Go modules 之前還有一個叫 dep 的項目,它也是 Go 的一個官方的實驗性項目,目的同樣也是為了解決 Go 在依賴管理方面的短板。在 Russ Cox 還沒有提出 Go modules 的時候,社區裡面幾乎所有的人都認為 dep 肯定就是未來 Go 官方的依賴管理解決方案了。

後來:誰都沒想到半路殺出個程咬金,Russ Cox 義無反顧地推出了 Go modules,這瞬間導致一石激起千層浪,讓社區炸了鍋。大家一致認為 Go team 實在是太霸道、太獨裁了,連個招呼都不打一聲。我記得當時有很多人在網上跟 Russ Cox 口水戰,各種依賴管理解決方案的專家都冒出來發表意見,討論範圍甚至一度超出了 Go 語言的圈子觸及到了其他語言的領域。

理想化

從他強制要求使用語義化版本控制這一點來說就很理想化了,如下:

類語言級:

這個關鍵詞其實是我自己瞎編的,我只是單純地個人認為 Go modules 在設計上就像個語言級特性一樣,比如如果你的主版本號發生變更,那麼你的代碼裡的 import path 也得跟著變,它認為主版本號不同的兩個模塊版本是完全不同的兩個模塊。此外,Go moduels 在設計上跟 go 整個命令都結合得相當緊密,無處不在,所以我才說它是一個有點兒像語言級的特性,雖然不是太嚴謹。

推 Go Modules 的人是誰

那麼在上文中提到的 Russ Cox 何許人也呢,很多人應該都知道他,他是 Go 這個項目目前代碼提交量最多的人,甚至是第二名的兩倍還要多。

Russ Cox 還是 Go 現在的掌舵人(大家應該知道之前 Go 的掌舵人是 Rob Pike,但是聽說由於他本人不喜歡川普執政所以離開了美國,然後他歲數也挺大的了,所以也正在逐漸交權,不過現在還是在參與 Go 的發展)。

Russ Cox 的個人能力相當強,看問題的角度也很獨特,這也就是為什麼他剛一提出 Go modules 的概念就能引起那麼大範圍的響應。雖然是被強推的,但事實也證明當下的 Go modules 表現得確實很優秀,所以這表明一定程度上的 「獨裁」 還是可以接受的,至少可以保證一個項目能更加專一地朝著一個方向發展。

總之,無論如何 Go modules 現在都成了 Go 語言的一個密不可分的組件。

GOPATH

Go modules 出現的目的之一就是為了解決 GOPATH 的問題,也就相當於是拋棄 GOPATH 了。

Opt-in

Go modules 還處於 Opt-in 階段,就是你想用就用,不用就不用,不強制你。但是未來很有可能 Go2 就強制使用了。

"module" != "package"

有一點需要糾正,就是「模塊」和「包」,也就是 「module」 和 「package」 這兩個術語並不是等價的,是 「集合」 跟 「元素」 的關係,「模塊」 包含 「包」,「包」 屬於 「模塊」,一個 「模塊」 是零個、一個或多個 「包」 的集合。

Go Modules相關屬性

go.mod

module example.com/foobar

go 1.13

require (

example.com/apple v0.1.2

example.com/banana v1.2.3

example.com/banana/v2 v2.3.4

example.com/pineapple v0.0.0-20190924185754-1b0db40df49a

)

exclude example.com/banana v1.2.4

replace example.com/apple v0.1.2 => example.com/rda v0.1.0

replace example.com/banana => example.com/hugebanana

go.mod 是啟用了 Go moduels 的項目所必須的最重要的文件,它描述了當前項目(也就是當前模塊)的元信息,每一行都以一個動詞開頭,目前有以下 5 個動詞:

這裡的填寫格式基本為包引用路徑+版本號,另外比較特殊的是 go $version,目前從 Go1.13 的代碼裡來看,還只是個標識作用,暫時未知未來是否有更大的作用。

go.sum

go.sum 是類似於比如 dep 的 Gopkg.lock 的一類文件,它詳細羅列了當前項目直接或間接依賴的所有模塊版本,並寫明了那些模塊版本的 SHA-256 哈希值以備 Go 在今後的操作中保證項目所依賴的那些模塊版本不會被篡改。

example.com/apple v0.1.2 h1:WX...

example.com/apple v0.1.2/go.mod h1:xHW...

example.com/banana v1.2.3/go.mod h1:HS...

...

我們可以看到一個模塊路徑可能有如下兩種:

example.com/apple v0.1.2 h1:WXk...

example.com/apple v0.1.2/go.mod h1:xH...

前者為 Go modules 打包整個模塊包文件 zip 後再進行 hash 值,而後者為針對 go.mod 的 hash 值。他們兩者,要不就是同時存在,要不就是只存在 go.mod hash。

那什麼情況下會不存在 zip hash 呢,就是當 Go 認為肯定用不到某個模塊版本的時候就會省略它的 zip hash,就會出現不存在 zip hash,只存在 go.mod hash 的情況。

GO111MODULE

這個環境變量主要是 Go modules 的開關,主要有以下參數:

GOPROXY

這個環境變量主要是用於設置 Go 模塊代理,主要如下:

它的值是一個以英文逗號 「,」 分割的 Go module proxy 列表(稍後講解)

作用:用於使 Go 在後續拉取模塊版本時能夠脫離傳統的 VCS 方式從鏡像站點快速拉取。它擁有一個默認值,但很可惜 proxy.golang.org 在中國無法訪問,故而建議使用 goproxy.cn 作為替代。

設置為 「off」 :禁止 Go 在後續操作中使用任 何 Go module proxy。

剛剛在上面,我們可以發現值列表中有 「direct」 ,它又有什麼作用呢?

其實值列表中的 「direct」 為特殊指示符,用於指示 Go 回源到模塊版本的源地址去抓取 (比如 GitHub 等),當值列表中上一個 Go module proxy 返回 404 或 410 錯誤時,Go 自動嘗試列表中的下一個,遇見 「direct」 時回源遇見 EOF 時終止並拋出類似 「invalid version: unknown revision...」 的錯誤。 

GOSUMDB

它的值是一個 Go checksum database,用於使 Go 在拉取模塊版本時(無論是從源站拉取還是通過 Go module proxy 拉取)保證拉取到的模塊版本數據未經篡改,也可以是「off」即禁止 Go 在後續操作中校驗模塊版本

格式: SUMDB_NAME+PUBLIC_KEY或SUMDB_NAME+PUBLIC_KEY SUMDB_URL。

擁有默認值: sum.golang.org (之所以沒有按照上面的格式是因為 Go 對默認值做了特殊處理)。

可被 Go module proxy 代理 (詳見:Proxying a Checksum Database)。

GOSUMDB 的默認值在中國無法訪問,故而更加建議將 GOPROXY 設置為 goproxy.cn,因為 goproxy.cn 支持代理 sum.golang.org。

Go Checksum Database

Go checksum database 主要用於保護 Go 不會從任何源頭拉到被篡改過的非法 Go 模塊版本,其作用(左)和工作機制(右)如下圖:

如果有興趣的小夥伴可以看看 Proposal: Secure the Public Go Module Ecosystem,有詳細介紹其算法機制,如果想簡單一點,查看 go helpmodule-auth 也是一個不錯的選擇。

GONOPROXY/GONOSUMDB/GOPRIVATE

這三個環境變量都是用在當前項目依賴了私有模塊,也就是依賴了由 GOPROXY 指定的 Go module proxy 或由 GOSUMDB 指定 Go checksum database 無法訪問到的模塊時的場景,他們具有如下特性:

它們三個的值都是一個以英文逗號 「,」 分割的模塊路徑前綴,匹配規則同 path.Match。

其中 GOPRIVATE 較為特殊,它的值將作為 GONOPROXY 和 GONOSUMDB 的默認值,所以建議的最佳姿勢是只是用 GOPRIVATE。

在使用上來講,比如 GOPRIVATE=*.corp.example.com 表示所有模塊路徑以 corp.example.com 的下一級域名 (如 team1.corp.example.com) 為前綴的模塊版本都將不經過 Go module proxy 和 Go checksum database,需要注意的是不包括 corp.example.com 本身。

Global Caching

這個主要是針對 Go modules 的全局緩存數據說明,如下:

同一個模塊版本的數據只緩存一份,所有其他模塊共享使用。

目前所有模塊版本數據均緩存在 $GOPATH/pkg/mod和  $GOPATH/pkg/sum 下,未來或將移至 $GOCACHE/mod和 $GOCACHE/sum 下( 可能會在當 $GOPATH 被淘汰後)。

可以使用 go clean-modcache 清理所有已緩存的模塊版本數據。

另外在 Go1.11 之後 GOCACHE 已經不允許設置為 off 了,我想著這也是為了模塊數據緩存移動位置做準備,因此大家應該儘快做好適配。

快速遷移項目至 Go Modules

遷移後 go get 行為的改變

這裡我們注意到有兩點比較特別,分別是:

第一點:為什麼 「拉取 hash 為 342b231 的 commit,最終會被轉換為 v0.3.2」 呢。這是因為雖然我們設置了拉取 @342b2e commit,但是因為 Go modules 會與 tag 進行對比,若發現對應的 commit 與 tag 有關聯,則進行轉換。

第二點:為什麼不建議使用 go mod vendor,因為 Go modules 正在淡化 Vendor 的概念,很有可能 Go2 就去掉了。

使用 Go Modules 時常遇見的坑坑 1: 判斷項目是否啟用了 Go Modules

坑 2: 管理 Go 的環境變量

這裡主要是提到 Go1.13 新增了 go env-w 用於寫入環境變量,而寫入的地方是 os.UserConfigDir 所返回的路徑,需要注意的是 go env-w 不會覆寫。

坑 3: 從 dep、glide 等遷移至 Go Modules

這裡主要是指從舊有的依賴包管理工具(dep/glide 等)進行遷移時,因為 BUG 的原因會導致不經過 GOPROXY 的代理,解決方法有如下兩個:

坑 4:拉取私有模塊

這裡主要想涉及兩塊知識點,如下:

坑 5:更新現有的模塊

坑 6:主版本號

Go Module Proxy 簡介

在這裡再次強調了 Go Module Proxy 的作用(圖左),以及其對應的協議交互流程(圖右),有興趣的小夥伴可以認真看一下。

Goproxy 中國

在這塊主要介紹了 Goproxy 的一些實踐操作以及 goproxy.cn 的一些 Q&A 和 近況,如下:

Q&A

Q:如果中國 Go 語言社區沒有咱們自己家的 Go Module Proxy 會怎麼樣?

A:在 Go 1.13 中 GOPROXY 和 GOSUMDB 這兩個環境變量都有了在中國無法訪問的默認值,儘管我在 golang.org/issue/31755 裡努力嘗試過,但最終仍然無法為咱們中國的 Go 語言開發者謀得一個完美的解決方案。所以從今以後咱 們中國的所有 Go 語言開發者,只要是 使用了 Go modules 的,那麼都必須先修改 GOPROXY 和 GOSUMDB 才能正常使用 Go 做開發,否則可能連一個最簡單的程序都跑不起 來(只要它有依 賴第三方模 塊)。

Q:我創建 Goproxy 中國(goproxy.cn)的主要原因?

A:其實更早的時候,也就是今年年初我也曾試圖在 golang.org/issue/31020 中請求 Go team 能想辦法避免那時的 GOPROXY 即將擁有的默認值可以在中國正常訪問,但 Go team 似乎也無能為力,為此我才堅定了創建 goproxy.cn 的信念。既然別人沒法兒幫忙,那咱們就 得自己動手,不為別的,就為了讓大家以後能夠更愉快地使用 Go 語言配合 Go modules 做開發。

最初我先是和七牛雲的許叔(七牛雲的 創始人兼 CEO 許式偉)提出了我打算 創建 goproxy.cn 的想法,本是抱著試試看的目的,但沒想到許叔幾乎是沒有超過一分鐘的考慮便認可了我的想法並表示願意一起推動。那一陣子剛好趕上我在寫畢業論文,所以項目開發完後就 一直沒和七牛雲做交接,一直跑在我的個人服 務器上。直到有一次 goproxy.cn 被攻擊了,一下午的功夫燒了我一百多美元,然後我才 意識到這種項目真不能個人來做。個人來做不靠 譜,萬一依賴這個項目的人多了,項目再出什麼事兒,那就會給大家􏰁成不必要的損 失。所以我趕緊和七牛雲做了交接,把 goproxy.cn 完全交給了七牛雲,甚至連域名都過戶了去。

近況

Goproxy 中國 (goproxy.cn) 是目前中國最可靠的 Go module proxy (真不是在自賣自誇)。

為中國 Go 語言開發者量身打造,支持代理 GOSUMDB 的默認值,經過全球 CDN 加速,高可用,可 應用進公司複雜的開發環境中,亦可用作上遊代理。

由中國倍受信賴的雲服務提供商七牛雲無償提供基礎設施支持的開源的非營利性項目。

目標是為中國乃至全世界的 Go 語言開發者提供一個免 費的、可靠的、持續在線的且經過 CDN 加速的 Go module proxy。

域名已由七牛雲進行了備案 (滬ICP備11037377號-56)。

情況

此處呈現的是存儲大小,主要是針對模塊包代碼,而一般來講代碼並不會有多大,0-10MB,10-50MB 佔最大頭,也是能夠理解,但是大於 100MB 的模塊包代碼就比較誇張了。

此時主要是展示了一下近期 goproxy.cn 的網絡數據情況,我相信未來是會越來越高的,值得期待。

Q&A

Q:如何解決 Go 1.13 在從 GitLab 拉取模塊版本時遇到的,Go 錯誤地按照非期望值的路徑尋找目標模塊版本結果致使最終目標模塊拉取失敗的問題?

A:GitLab 中配合 goget 而設置的 <meta> 存在些許問題,導致 Go 1.13 錯誤地識別了模塊的具體路徑,這是個 Bug,據說在 GitLab 的新版本中已經被修復了,詳細內容可以看 https://github.com/golang/go/issues/34094 這個 Issue。然後目前的解決辦法的話除了升級 GitLab 的版本外,還可以參考 https://github.com/developer-learning/night-reading-go/issues/468#issuecomment-535850154 這條回復。

Q:使用 Go modules 時可以同時依賴同一個模塊的不同的兩個或者多個小版本(修訂版本號不同)嗎?

A:不可以的,Go modules 只可以同時依賴一個模塊的不同的兩個或者多個大版本(主版本號不同)。比如可以同時依賴 example.com/foobar@v1.2.3 和 example.com/foobar/v2@v2.3.4,因為他們的模塊路徑(module path)不同,Go modules 規定主版本號不是 v0 或者 v1 時,那麼主版本號必須顯式地出現在模塊路徑的尾部。但是,同時依賴兩個或者多個小版本是不支持的。比如如果模塊 A 同時直接依賴了模塊 B 和模塊 C,且模塊 A 直接依賴的是模塊 C 的 v1.0.0 版本,然後模塊 B 直接依賴的是模塊 C 的 v1.0.1 版本,那麼最終 Go modules 會為模塊 A 選用模塊 C 的 v1.0.1 版本而不是模塊 A 的 go.mod 文件中指明的 v1.0.0 版本。

這是因為 Go modules 認為只要主版本號不變,那麼剩下的都可以直接升級採用最新的。但是如果採用了最新的結果導致項目 Break 掉了,那麼 Go modules 就會 Fallback 到上一個老的版本,比如在前面的例子中就會 Fallback 到 v1.0.0 版本。

Q:在 go.sum 文件中的一個模塊版本的 Hash 校驗數據什麼情況下會成對出現,什麼情況下只會存在一行?

A:通常情況下,在 go.sum 文件中的一個模塊版本的 Hash 校驗數據會有兩行,前一行是該模塊的 ZIP 文件的 Hash 校驗數據,後一行是該模塊的 go.mod 文件的 Hash 校驗數據。但是也有些情況下只會出現一行該模塊的 go.mod 文件的 Hash 校驗數據,而不包含該模塊的 ZIP 文件本身的 Hash 校驗數據,這個情況發生在 Go modules 判定為你當前這個項目完全用不到該模塊,根本也不會下載該模塊的 ZIP 文件,所以就沒必要對其作出 Hash 校驗保證,只需要對該模塊的 go.mod 文件作出 Hash 校驗保證即可,因為 go.mod 文件是用得著的,在深入挖取項目依賴的時候要用。

Q:能不能更詳細地講解一下 go.mod 文件中的 replace 動詞的行為以及用法?

A:這個 replace 動詞的作用是把一個「模塊版本」替換為另外一個「模塊版本」,這是「模塊版本」和「模塊版本(module path)」之間的替換,「=>」標識符前面的內容是待替換的「模塊版本」的「模塊路徑」,後面的內容是要替換的目標「模塊版本」的所在地,即路徑,這個路徑可以是一個本地磁碟的相對路徑,也可以是一個本地磁碟的絕對路徑,還可以是一個網絡路徑,但是這個目標路徑並不會在今後你的項目代碼中作為你「導入路徑(import path)」出現,代碼裡的「導入路徑」還是得以你替換成的這個目標「模塊版本」的「模塊路徑」作為前綴。

另外需要注意,Go modules 是不支持在 「導入路徑」 裡寫相對路徑的。舉個例子,如果項目 A 依賴了模塊 B,比如模塊 B 的「模塊路徑」是 example.com/b,然後它在的磁碟路徑是 ~/b,在項目 A 裡的 go.mod 文件中你有一行 replace example.com/b=>~/b,然後在項目 A 裡的代碼中的「導入路基」就是 import"example.com/b",而不是 import"~/b",剩下的工作是 Go modules 幫你自動完成了的。

然後就是我在分享中也提到了, exclude 和 replace 這兩個動詞只作用於當前主模塊,也就是當前項目,它所依賴的那些其他模塊版本中如果出現了你待替換的那個模塊版本的話,Go modules 還是會為你依賴的那個模塊版本去拉取你的這個待替換的模塊版本。

舉個例子,比如項目 A 直接依賴了模塊 B 和模塊 C,然後模塊 B 也直接依賴了模塊 C,那麼你在項目 A 中的 go.mod 文件裡的 replace c=>~/some/path/c 是只會影響項目 A 裡寫的代碼中,而模塊 B 所用到的還是你 replace 之前的那個 c,並不是你替換成的 ~/some/path/c 這個。

總結

在 Go1.13 發布後,接觸 Go modules 和 Go module proxy 的人越來越多,經常在各種群看到各種小夥伴在諮詢,包括我自己也貢獻了好幾枚 「坑」,傲飛的這一次 《Go Modules、Go Module Proxy 和 goproxy.cn》的技術分享,非常的有實踐意義。如果後續大家還有什麼建議或問題,歡迎隨時來討論。

最後,感謝在 goproxy.cn 背後的人們(@七牛雲 和 @盛傲飛)對中國 Go 語言社區的無私貢獻和奉獻。

進一步閱讀

night-reading-go/issues/468

B站:【Go 夜讀】第 61 期 Go Modules、Go Module Proxy 和 goproxy.cn

youtube:【Go 夜讀】第 61 期 Go Modules、Go Module Proxy 和 goproxy.cn


相關焦點

  • Go 問題集 - cannot find main module; packages.Load error
    If you believe this is a mistake, please file an issue: https://github.com/golang/go/issues/new. go [-e -json -compiled=true -test=true -export=false -deps=true -find=false -- ./]: exit status 1: go: cannot
  • go modules:使用mod管理項目依賴包,通過vendor一鍵分發編譯包
    如果是不同平臺,通過go.mod文件重新下載依賴即可。如果網絡不穩定,還可以通過export GOPROXY=https://goproxy.io設置網絡代理。依賴包版本號格式在理解mod的工作方式之前,需要先了解一下go語言軟體我版本號的組成。
  • 【Go技術】Go Modules概述
    GOPROXY的值是一個以英文逗號 「,」 分割的Go module proxy列表,允許設置多個模塊代理,如果不想使用也可以將其設置為 「off」 ,這將會禁止Go從任何地方拉取模塊版本。文件格式如下所示 <module> <version>/go.mod <hash>或者<module> <version> <hash><module> <version>/go.mod <hash>
  • 一篇文章教會你如何使用Go語言Modules
    它和傳統的直接go get區別在哪沒有使用go modules時,我們直接go get下載的包,會默認放在%GOPATH%/src目錄下。啟用go modules後,包都會下載到%GOPATH%/pkg/mod文件夾中。
  • Go 語言設計哲學之十三:理解包導入路徑的含義
    這樣,Go編譯器在編譯某包M時,針對M依賴的每個包導入(比如:導入包N),只需讀取一個目標文件即可(比如:N包編譯成的目標文件,該目標文件中已經包含了N包的依賴包的導出信息),而無需再讀取其他文件中的信息了。通過 package 關鍵字聲明 Go 源文件所屬的包: 上述源碼表示:文件 xx.go 是包 x 的一部分。
  • Go Modules v2 及後續版本
    這篇文章探討了主版本的語義,如何創建和發布一個新的主版本,以及如何維護一個模塊的多個主版本。主版本和模塊路徑模塊形成了了 Go 中的一個重要原則,即導入兼容性規則:💡如果舊的包和新的包有同樣的導入路徑,新的包必須兼容舊的包。根據定義,包的新主版本與以前的版本不向後兼容。這意味著模塊的新主版本必須具有與前一個版本不同的模塊路徑。
  • 人到中年,把這兩個字的含義參透清楚,煩惱會逐漸遠離你
    小時候生活的無憂無慮,擁有著童年的天真與活潑,但進入青春期後,煩惱開始逐漸增多,到了三四十歲乃至六十歲,呈現出最高峰,而過了60歲以後,兒孫滿堂,壓力相對較少,可以慢慢步入老年生活,安享餘生。由此看來,處在中年時期的人,煩惱最多,不管是工作上還是生活中,所有的壓力凝聚在一起,像一座巨山壓得人喘不過氣。
  • Go語言學習筆記(五):切片操作
    不過,有一些高手也基於這個包做出了另一個可以嵌入Jupyter的插件,在那裡面,可以實現彩色顯示,更重要的是,可以利用Jupyter lab的許多功能。關於Jupyter lab這個工具,在本公眾號之前的文章中有介紹過。
  • python包package和模塊module導入深入詳解
    源 / 戀習Python      文 / EarlGrey作為一名新手Python程式設計師,你首先需要學習的內容之一就是如何導入模塊或包具體來說,是使用句點來決定如何相對導入其他包或模塊。這麼做的原因是為了避免偶然情況下導入標準庫中的模塊產生衝突。
  • 2021再看Deno
    這個改進雖說不算新,但反響確實很好,大概是天下人苦npm(npm開玩笑的說法是:你怕嗎)久已,用法簡單,高效,甚至是衍生出很多關於CDN for JavaScript modules的思考。下面,我們就一起看一下吧。
  • 第 61 期 乾貨滿滿的 Go Modules 和 goproxy.cn
    本次分享將討論如何使用模塊和模塊代理,以及在它們的使用中會常遇見的坑,還會講解如何快速搭建自己的私有模塊代理,並簡單地介紹一下七牛雲推出的 goproxy.cn 以及它的出現對於中國 Go 語言開發者來說重要在何處。
  • gofair翻譯平臺,如何下載安裝gofair_APP?
    gofair翻譯平臺,如何下載安裝gofair APP?gofair有APP,目前提供以下兩種方式安裝。方法1:通過電腦下載gofair首頁頂部或底部找到「APP for Android 」按鈕,下載後把文件發送到手機安裝即可。方法2:通過手機安裝用手機上gofair任何一個頁面,點擊頁面底部「APP for Android 」按鈕,下載安裝即可。
  • Go 1.14中值得關注的幾個變化
    如果你沒有自己調用syscall包,那麼異步搶佔調度對你已有的代碼幾乎無影響。Go 1.14的異步搶佔調度在windows/arm, darwin/arm, js/wasm, and plan9/*上依然尚未支持,Go團隊計劃在Go 1.15中解決掉這些問題。2. defer性能得以繼續優化在Go 1.13中,defer性能得到理論上30%的提升。
  • Go語言正確快速安裝開發工具
    就在下載Go語言的工具,但是又被牆了。只能在網上亂搜。剛搗鼓好,做個簡單的記錄。export GOPROXY=https://goproxy.io/開啟go module 功能export GO111MODULE=on開始下載工具go get -u -v github.com/mdempsky/gocodego get -u -v github.com/uudashr/gopkgs/cmd/gopkgsgo get
  • 2021再看Deno(關於CDN for JavaScript modules的思考)
    的文章,正好最近有一些研究,站在2021年再來看看deno。無疑,deno改變了大家的對包管理的看法。本身deno夠小,試錯成本低,它確確實實引領了一個潮流方向。這個改進雖說不算新,但反響確實很好,大概是天下人苦npm(npm開玩笑的說法是:你怕嗎)久已,用法簡單,高效,甚至是衍生出很多關於CDN for JavaScript modules的思考。
  • 分手最絕情的星座,從此不再聯絡,再無任何瓜葛
    感情中金牛可是非常絕情的,既然不愛了,就不會給對方任何機會,那股衝動勁怎麼都拉不住。如果跟戀人分手了,白羊很少會與前任再有瓜葛,轉身瀟灑離去,絕不再回首。水瓶座水瓶座的人腦洞特別大,總會產生一些天馬行空的想法,與TA戀愛可是非常開心甜蜜的。
  • 從此再無煩惱
    艾倫·錫克1947年生於加拿大,走進《成長的煩惱》劇組之前,他做過演員,也做過電視節目主持人和音樂創作人,但演藝之路卻並不順利。他曾經與美國著名的脫口秀主持人約翰尼·卡森較量並以慘敗告終。但1985年,《成長的煩惱》劇組並未因此而否定他,相反,在150個競爭者中看中了他,讓他飾演父親傑森·西佛一角。
  • 再談「Go Dutch」
    go Dutch的意思是「各自付自己的帳.平攤費用」(pay one's own expenses,share expenses)。Dutch原為「荷蘭或荷蘭人」之義,go Dutch為何卻有與之截然不同的含義呢?不少英語學習者對此百思不得其解,有的甚至妄加揣測,以為荷蘭人過分精明、以致斤斤計較,不願意分擔朋友的費用,是小氣之流。  荷蘭人當然並非吝嗇之輩。那麼go Dutch的含義究竟是如何產生的呢?這裡頭還有一段有趣的史話呢。  17世紀以前,英國海上實力十分強大。
  • facebook臉書安裝包下載
    還在為尋找facebook臉書安裝包下載而煩惱嗎?那就來18183來看看吧!facebook臉書安裝包下載使用方法:facebook臉書安裝包下載仿佛有一股魔力一樣,讓你開始就停不下來。
  • 【不正經教學】如何在CS:GO裡裝高手
    不正經教學又來了,只為開心看看如何在CS:GO裡假裝高手本文僅供娛樂,切勿對號入座