Escape analysis issues of strings builder

在分享 Go string to slice 議題 文章後,有朋友(感謝@陳孝思)在社團裡面分享另一個議題,關於在 strings package 的 builder 中有避免 escape analysis 的方式。基於這個分享,我就去查閱了相關 source code 和 issues ,並且整理成此文章。

Escape analysis

escape analysis 是協助 Go compiler 判斷要將 variable 分配在 goroutine stack 還是 heap 的方式,而由於變數的分配位置會關係到 garbage collection 進而影響效能,因此 escape analysis 也是 Gopher 所在意的議題之一。

Go string to slice 議題

日前在看 Go runtime/string.go source code 的時候,意外看到一篇文章 Go中string转[]byte的陷阱,不過這篇文章的日期間隔已久,Go version 也從文章中的 1.10 改版到 1.14 了,所以想要更新一下這個議題現況。

hugo

Version

Go version: 1.14

問題摘要

1. runtime.stringtoslicebyte

首先,文章中提到的例子:

1
2
3
4
5
6
7
func main() {
    s := []byte("")
    s1 := append(s, 'a')
    s2 := append(s, 'b')
    //fmt.Println(s1, "==========", s2)
    fmt.Println(string(s1), "==========", string(s2))
}

在沒有 fmt.Println(s1, "==========", s2) 這一行的情況下,output 會產生:

Side Project - Transfer.sh

Trace transfer.sh open project 有提到我目前正在調整 transfer.sh 這個 open source project,把它修改成內部所需要的一個 service,而之前已經改得差不多了,所以簡單地來介紹一下修改了哪些內容:

需求

  1. 每個 download request 能依需求驗證 IP address 和 user account / password
  2. 能使用外部 service 來驗證 user account
  3. 需能支援 curl cmd tool
  4. k8s deployment

修改項目

1. Middleware Chain

根據需求 1,在 getHandler 前加入 middleware chain,其中包含:

Side Project - Symlink Generator for Multi-lang Hugo Site

Multilingual Mode in Hugo 這篇文章中有提到目前使用 Hugo site generator 產生 multi-lang site 的問題,使用者必須要為每個語言都建立一個檔案,才不會造成最後在產生網站後,發生某一個語言的頁面遺失問題。(例如,使用者一定要建立 about.md, about.tw.md,這樣當瀏覽者在選擇中文語言的網站時,才會顯示出 about 頁面)。這樣其實會造成不少困擾,因為不是每個語言都可以這麼即時的被翻譯完成,但我們又不希望有頁面遺失,因此需要透過一些方式來解決這個問題。

而其中一個方法就是建立一個 symbolic link,當某個語言還沒被翻譯時,就建立一個 symbolic link 來代表這個檔案,然後實際檔案則指向預設語言的檔案。

因此,side project github.com/YuShuanHsieh/hugo-langs-symlink 就是為了這個目的而誕生的,用我熟悉的 Go 語言來編寫,使用者可以透過參數來決定要建立 symbolic link 的語言和檔案對象。Project 簡單地提供 createremove 兩個 sub command ,這樣用戶就能直接在 local 端操作和刪除 symbolic link,避免產生過多的 symbolic link 而影響到 git commit。

Discourse Forums Deployment

這兩天在試著部署 Discourse -目前主流的 forum open porject。雖然它有 cloud 版本可以用,不過因為基於一些因素,我們打算先自行部署,給團隊成員實際試用測試過後,再來看是否要使用官方提供的 Cloud 付費版本。而在部署的過程中發現蠻多問題的,所以也一併記錄下來,給想要自行部署的人參考。

Discourse Container

首先在 Discourse container 部份,我們選擇由 bitnami 所維護的 bitnami/discourse 版本,原因是它提供相對完整的 configuration 和流程,事後證明這個選擇也是對的,因為我有嘗試使用 Discourse 所提供的 container 來部署,結果根本是場災難,畢竟官方所提供的 container 本來就不適合用在自行部署,除了流程複雜之外,size 也大許多 (2.5GB)。

Version

Discourse 版本部分,目前 (2020/04) 官方是 2.5.0 beta,而 bitnami/discourse 則是 2.4.1 也就是官方所提供的最新穩定版本,因此不會有太大的版本落差。

Trace transfer.sh open project

因為工作需求,需要一個透過 cli 就可以 upload 和 download 的工具,剛好 open project transfer.sh 有提供類似的功能,不過我們有額外的需求,包含每個 request 都要能 fiter IP 和執行 HTTP Basic Auth 驗證,因此就有這個機會來分析一下 transfer.sh source code 並且後續可以針對我們需求來修改!

Source code 分析

HTTP Router

首先來看 transfer.sh 的 source code,這個 project 其實程式碼蠻少的,所以大概花個幾個小時就可以大致了解運作方式。transfer.sh 是一個簡單的 Web server,其 path router 是使用 gorilla/mux,雖然 gorilla/mux 的 path search 是 slice 設計, route 效率不比 radix tree router 效能好,不過因為這個 Web server 的 path 也不多,所以就還可以接受。

Multilingual Mode in Hugo

紀錄用 Hugo site generator 建立多語言網站時所遇到的問題,與過程中相關的學習內容,包含 Hugo render 過程、source code trace 等。

預備知識

The flow of Hugo Render

Hugo 是一個 Site Generator,那他是怎麼產出這些 static html 的呢?首先程式會先遍歷在 content folder 底下所有的 folder 和 file,並且組成一個 contentTree (題外話, contentTree 是採用 radix 資料結構)。然後再把這些 content node 根據 node type (e.g. type 可能是 sections or taxonomies) 去對應到 layout folder 內的 template,接著 render 出最後的 html 頁面。(也可參閱 hugolib/site.go 由 Hugo 開發者所寫的簡易流程)

Go HTTP Routers - Chi/Echo/Gin/gorilla mux 實作細節與比較

前言

之前做 API server,制定 route path 時有遇到一些問題,於是就順手看了幾個 HTTP router / web framework 的 router 部分實作方式,並且記錄下來,提供給大家做個參考。

問題

需要加入

  1. /stations/instances
  2. /stations/{id}

這兩個 path 對應到不同的 handlers。

Chi

package github.com/go-chi/chi

知名 HTTP router library chi,其輕量、快速、handler 使用原生 net/http struct,都是不錯的優勢。和多數主流的 HTTP router 相似,chi 的 router 是採用 radix tree 結構,比較特別的是 chi 將 node type 分成四種:

Start HTTP/2 running over cleartext TCP

![flow]({{ site.url }}/assets/images/h2c-flow.png)

前言

主流使用 HTTP/2 時都是基於 TLS protocol,不過在 HTTP/2 RFC7540 規範中, HTTP/2 其實也可以直接基於 cleartext TCP 來溝通。這次主要介紹 based on cleartext TCP 的 HTTP/2 server 與 client 實作,後續會再加入 HTTP/2 結合 TLS protocol 的相關內容。

HTTP/2 Version Identification

RFC7540 3.1 中有明確定義出 HTTP/2 on TLS protocol or cleartext TCP 的識別號,這個識別主要用於 client 端詢問 server 對於 HTTP/2 的 protocol 支援,以及切換到 HTTP/2 的過程。

Go - Archive files with archive/tar lib

前言

由於專案要提供 API 來讓使用者 export 匯出檔案, 因此需要將所需檔案集結成一個 archive file。這個流程是透過 Go 的標準 lib archive/tar 來處理,以下文章將簡單介紹流程和實作方式,並於最後附上完整程式碼。

Tar

tar 在UNIX/Linux系統中是最常見的打包工具,透過 tar 的協助,我們可以把數個檔案打包成一個 <file name>.tar 檔案,以利進行後續處理。

![Go-Tar-1.png]({{ site.url }}/assets/images/Go-Tar-1.png)

tar file format

.tar 的檔案格式主要是由 file object 和其對應的 header 所組成。 header 裡面包含了一個 file 的 metadata(例如檔案名稱,數據大小等),這樣系統就可以透過 header 去檢測檔案屬性和完整度。