一些Golang小技巧

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

今天給大家介紹3個我覺得比較有啟發的Golang小技巧,分別是以下幾個程式碼片段

  • nsq裡的select寫檔案和socket
  • io模組裡的sendfile
  • fasthttp裡對header的處理

nsq裡的select讀

在nsq中,需要讀取之前磁碟上的,或者是從記憶體中直接讀取,一般人都是先判斷記憶體中有沒有資料,然而,nsq另闢蹊徑使用了select語句,把CSP模式用到了極致。

源檔案連結:channel.go

        select {        case msg = <-c.memoryMsgChan:  //嘗試從記憶體中讀取        case buf = <-c.backend.ReadChan(): //如果記憶體中沒有,直接從磁碟上讀取            msg, err = decodeMessage(buf)            if err != nil {                c.ctx.nsqd.logf("ERROR: failed to decode message - %s", err)                continue            }

io模組中的sendfile

經過精巧的io.ReadFrom interface設計,sendfile對上層的http handler完全透明,具體調用

    +----------------+    | http.ServeFile |    +--------+-------+             |    +--------+--------+      +----------------+            +---------------------------------+    |     os.File     +------>     io.Copy    |            | http.Response                   |    +--------+--------+      +--------+-------+            | +-----------------------------+ |             |                        |                    | | net.TCPConn                 | |             |               +--------v-------+  2. has?   | | +-------------------------+ | |             |               |  io.CopyBuffer +--------->  | | | io.ReadFrom             | | +-----+             |               +--------+-------+            | | | +---------------------+ | | |     |             |                        |                    | | | | sednfile (syscall)  | | | |     |             |                        |                    | | | +---------------------+ | | |     |             |                        |                    | | +-------------------------+ | |     |             |                        |                    | +-----------------------------+ |     |             |                        |                    +---------------------------------+     |             |   4. do it!   +--------v------+   3. YES!                                           |             +--------------->     syscall   <-----------------------------------------------------+                             +----------------
  1. http模組對於檔案只是簡單地直接開啟,擷取檔案描述符(file descriptor)
  2. http模組調用io.Copy函數,io.Copy函數開始檢查Reader Writer是否特殊的ReadFrom,WriteTo介面
    func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {    // bla....    // Similarly, if the writer has a ReadFrom method, use it to do the copy.       if rt, ok := dst.(ReaderFrom); ok {      return rt.ReadFrom(src)      }
  1. 完成判斷,並直接調用net.TCPConn模組下的ReadFrom介面,裡面寫上了sendfile
func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {        if n, err, handled := sendFile(c.fd, r); handled {        if err != nil && err != io.EOF {       err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}       }       return n, err       }    // skipped....

這樣io.Copy的使用者其實不知道自己默默地用了sendfile,同時又保持了介面一致性和很低的耦合度。

更深入的可以移步謝大的教程- interface

fasthttp對於header的處理

fasthttp為什麼會比net.http快,其中一個原因就是fasthttp並沒有完全地解析所有的http請求header資料。這種做法也稱作lazyloading。首先我們從header的struct開始看起吧。

type RequestHeader struct {        //bla.....    contentLength      int    contentLengthBytes []byte    method      []byte    requestURI  []byte    host        []byte    contentType []byte    userAgent   []byte    h     []argsKV    bufKV argsKV    cookies []argsKV    rawHeaders []byte}

可能大家都很奇怪,Request裡沒有string,明明method、host都可以用string啊,這是由於string是不可變類型,而從Reader中讀出的[]byte是可變類型,因此,從[]byte轉化為string時是有copy和alloc行為的。雖然資料量小時,沒有什麼影響,但是構建高並發系統時,這些小的資料就會變大變多,讓gc不堪重負。

request中還有一個特殊的argsKV

type argsKV struct {    key   []byte    value []byte}

其實和上面的理由是一樣的,net.http中使用了map[string]string來儲存各種其他參數,這就需要alloc,為了達成zeroalloc,fasthttp採用了遍曆所有header參數來返回,其實也有一定的考慮,那就是大部分的header數量其實都不多,而每次對於短key對比只需要若干個CPU周期,因此算是合理的tradeoff(詳見bytes.Equal彙編實現)

對於[]byte alloc的最佳化,可以參考Dave Cheney的《Five things that make gofast》

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.