<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                本文譯自go-proverbs, 脫胎于 Rob Pike 振奮人心的演講視頻 talk at Gopherfest SV 2015 (bilibili). 不要通過共享內存進行通信, 通過通信共享內存 (Don't communicate by sharing memory, share memory by communicating) 傳統的線程模型(通常在編寫 Java, C++ 和 Python 程序時使用)要求程序員使用共享內存在線程之間進行通信. 通常, 共享數據結構受鎖保護, 線程將爭奪這些鎖訪問數據, 在某些情況下, 通過使用 Python 的 Queue 等線程安全的數據結構可以使這變得更容易. Go 的并發原語 (goroutines 和 channels) 為構造并發軟件提供了一種優雅而獨特的手段. (這些概念有一個有趣的歷史, 要從 C.A.R.Hoare 的通信順序進程說起.) Go 鼓勵使用 channels 在 goroutines 之間傳遞對數據的引用, 而不是顯式地使用鎖來調解對共享數據的訪問. 這種方法確保只有一個 goroutine 可以在給定的時間訪問數據. 這個概念總結在 Effective Go 文檔中 (任何 Go 程序員都必須閱讀). Go 官方博客中有一篇文章對該諺語解讀, 可以參見原文. 并發不是并行 (Concurrency is not parallelism) 當人們聽到 并發 這個詞的時候, 他們經常會想到并行, 這是一個相關的, 但非常獨特的概念. 在編程中, 并發是獨立執行的進程的組成, 而并行則是 (可能相關的) 計算的同時執行. 并發是一次處理很多事情. 并行是一次做很多事情. Channels 重排序; 互斥量串行化 (Channels orchestrate; mutexes serialize) 這個看中文(翻譯待商榷)是不是一臉懵 (雖然英文也看不懂) ? 其實分號前后說的是一個意思, 該諺語按我的個人理解可以用 go 程序 (來自 go tour) 解釋成如下: ~~~ package main import "fmt" func sum(s []int, c chan int) { sum := 0 for _, v := range s { sum += v } c <- sum // 此處如果改成互斥量一樣可以做到 } func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := <-c, <-c fmt.Println(x, y, x+y) } ~~~ 接口越大, 抽象越弱 (The bigger the interface, the weaker the abstraction) 接口背后的概念是通過將對象的行為抽象為簡單的契約來允許重用性. 雖然接口不是 Go 專有的, 但由于 Go 接口通常趨向于小型化, Go 程序員才廣泛使用它們. 通常情況下, 一個接口只限于一到兩個方法. Go io 包接口就是典型的例子. 充分利用零值 (Make the zero value useful) 零值的典型例子如 bytes.Buffer 和 sync.Mutex: ~~~ var buf bytes.Buffer buf.Write([]byte("hello")) fmt.Println(buf.String()) var mu sync.Mutex mu.Lock() mu.Unlock() ~~~ 這樣看起來是不是感覺一點用沒有 ? 如果這樣呢 ? ~~~ type Map struct { mu sync.RWMutex // ... } func (m *Map) Set(k, v interface{}) { m.mu.Lock() defer m.mu.Unlock() if m.m == nil { m.m = make(map[interface{}]interface{}) } m.m[k] = v } ~~~ interface{} 言之無物 (interface{} says nothing) 該諺語不是說 interface {} 不代表任何東西, 而是說該類型無靜態檢查以及調用時保證, 比如你的 func 接收一個 interface{} 類型, 你寫的時候是可用的, 但是某個時間你進行了代碼重構可能壞掉了. Gofmt 的風格沒有人喜歡, 但是 gofmt 是每個人的最愛 (Gofmt's style is no one's favorite, yet gofmt is everyone's favorite) 該諺語告訴我們少些風格之爭, 用這些時間多寫代碼. 小復制好過小依賴 (A little copying is better than a little dependency) 簡單說就是如果你可以手動擼小快代碼就不要導入一個庫去做, 比如 UUID: ~~~ // see: https://groups.google.com/d/msg/golang-nuts/d0nF_k4dSx4/rPGgfXv6QCoJ package main import ( "fmt" "os" ) func main() { f, _ := os.Open("/dev/urandom") // 演示用忽略 errcheck b := make([]byte, 16) f.Read(b) f.Close() uuid := fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) fmt.Println(uuid) } ~~~ 雖然有一堆寫好的 UUID 庫, 當你僅僅需要一個 UUID v4 實現. 系統調用必須始終使用構建標簽保證 (Syscall must always be guarded with build tags) 不同的系統 (*NIX, Windows) 調用導致你同一個 func (實現并不一樣) 可能需要在不同的系統上構建才能得到你想要的結果. 簡單說就是系統調用不可移植才這么干. 示例可參見 Go 標準庫 syscall. Cgo 必須始終使用構建標簽保證 (Cgo must always be guarded with build tags) 基本上原因同上一條. Cgo 不是 Go (Cgo is not Go) 如果可能不要用 Cgo. 這里有篇文章說明了為什么. unsafe 包無保證 (With the unsafe package there are no guarantees) 包如其名, 不安全. 你可以使用 unsafe 包如果你準備好了有一天它會壞掉. 清晰好過聰明 (Clear is better than clever) Rob Pike 在他與別人合著的 <程序設計實踐> 中寫到: "寫清晰的代碼, 不要寫聰明的代碼". 反射永遠不是清晰的 (Reflection is never clear) 很多人在 Stackoverflow 上抱怨 Go 的反射不工作, 因為那不是為你準備的??! 只有很少很少的人應該用反射這個非常強大而又非常難的特性. 新手應該遠離反射和 interface{}. 錯誤也是一種值 (Errors are values) 值可以被編程, 并且由于錯誤是值, 所以錯誤可以被編程. Go 官方博客有對此的解讀. 不要止步于檢查錯誤而要優雅的處理 (Don't just check errors, handle them gracefully) Dave Cheney 有篇博客詳細解讀了該諺語. 設計架構, 命名組件, 記錄細節 (Design the architecture, name the components, document the details) 當你寫一個大型系統的時候, 你把它設計成一種結構化的東西. 想象組件的每一個部分并行工作, 為不同的組件起好的名字, 因為這些名字會出現在稿紙上. 拿 Go 程序來說, 如果名字不錯, 組件就好理解, 那么程序的結構設計就會清晰, 程序會感覺很自然. 但是還有很多東西你需要解釋, 所以這些是你需要解釋的細節. 但是命名會幫助你解釋很大一部分設計. 細節只是填補材料的缺口可能用來為用戶打印工程圖解文檔. 文檔是針對用戶的 (Documentation is for users) 很多人寫文檔表明某個 func 是做什么的, 但是他們不想想這個 func 是為誰而寫. 這有很大的不同. 你知道這個 func 返回什么是對的, 但是它為什么返回了你使用的時候不一樣的結果? 把自己當成使用者而不是寫它的人, 那么 godoc 上的文檔就是對用戶有用的. 這對于其他語言一樣適用. 不要慌 (Don't panic) 不要使用 panic 進行正常的錯誤處理. 使用錯誤 (error) 和多個返回值. ![](https://box.kancloud.cn/032176b8778dbc41f1ce6b79a83d59c1_900x350.jpg)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看