成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我們應該怎么樣編寫 Go 語言庫,有哪些標準可以參考?

開發 后端
不久前我和朋友們想出一個主意,準備合并我們的 IRC bots,并用 Go 重寫它們。為了防止重寫大部分現有功能,我們試圖找到支持 bots 程序中使用的 Web API 的現有庫。我們的項目需要一個 Reddit API 的庫。這篇文章啟發于我找到的前三個庫,我不打算說出它們的名字,以免羞辱它們的作者。

 不久前我和朋友們想出一個主意,準備合并我們的 IRC bots,并用 Go 重寫它們。為了防止重寫大部分現有功能,我們試圖找到支持 bots 程序中使用的 Web API 的現有庫。我們的項目需要一個 Reddit API 的庫。這篇文章啟發于我找到的前三個庫,我不打算說出它們的名字,以免羞辱它們的作者。

[[314065]]

上面說的每一個庫都存在一些基本問題以至于它們在真實場景中不可用。并且每個庫都以這樣一種方式編寫:不以非向后兼容的方式修改現有庫的 API,這樣是不可能修復問題的。不幸的是,由于很多其他的庫也存在同樣的問題,所以我會在下面列出一些作者錯誤的地方。

不要對 HTTP 客戶端硬編碼

很對庫都包含了對 http.DefaultClient 的硬編碼。雖然對庫本身來說這并不是問題,但是庫的作者并未理解應該怎樣使用 http.DefaultClient 。正如 default client 建議它只在用戶沒有提供其他 http.Client 時才被使用。相反的是,許多庫作者樂意在他們代碼中涉及 http.DefaultClient 的部分采用硬編碼,而不是將它作為一個備選。這會導致在某些情況下這個庫不可用。

首先,我們很多人都讀過這篇講述 http.DefaultClient 不能自定義超時時間的文章《Don’t use Go’s default HTTP client (in production)[1]》,當你沒法保證你的HTTP 請求一定會完成(或者至少要等一個完全無法預估時間的響應)時,你的程序可能會遇到奇怪的 goroutine 泄漏和一些無法預知的行為。在我看來,這會是每一個對 http.DefaultClient 采用硬編碼的庫不可用。

其次,網絡需要一些額外的配置。有時候需要用到代理,有時候需要對 URL 進行一丟丟的改寫,甚至可能 http.Transport 需要被一個定制的接口替換。當一個程序員在你的庫里用他們自己的 http.Client 實例時,以上這些都很容易被實現。

在你的庫中處理 http.Client 的推薦方式是使用提供的客戶端,但是如果需要的話,有一個默認的備選:

 

  1. func CreateLibrary(client *http.Client) *Library {    if client == nil {        client = http.DefaultClient    }    ...} 

或者如果你想從工廠函數中移除參數,請在你的 struct 中定義一個輔助方法,并且讓用戶在需要時設置其屬性:

 

  1. type Library struct {    Client *http.Client}func (l *Library) getClient() *http.Client {    if l.Client == nil {        return http.DefaultClient    }    return l.Client} 

另外,如果一些全局的特性對于每個請求來講都是必須的,人們經常感覺到需要用他們自己的實例來替換 http.Client。這是一個錯誤的方法 — 如果你需要在你的請求中設置一些額外的 headers,或者在你的客戶端引入某類公共的特性,你只需要簡單為每個請求進行設置或者用組裝定制客戶端的方式來代替完全替換它。

不要引入全局變量

另一個反面模式是允許用戶在一個庫中設置全局變量。舉個例子,在你的庫中允許用戶設置一個全局的 http.Client 并被所有的 HTTP 調用執行:

 

  1. var libraryClient *http.Client = http.DefaultClientfunc SetHttpClient(client *http.Client) {    libraryClient = client} 

通常在一個庫中不應該存在一堆全局變量。當你寫代碼的時候,你應該想想用戶在他們的程序中多次使用你的這個庫會發生什么。全局變量會使不同的參數沒有辦法被使用。而且,在你的代碼中引入全局變量會引起測試上的問題并造成代碼上不必要的復雜度。使用全局變量可能會導致在你程序的不同模塊有不必要的依賴。在寫你的庫的時候,避免全局狀態是格外重要的。

返回 structs,而不是 interfaces

這是一個普遍的問題(實際上我在這一點上也犯過錯)。很多庫都有下面這類函數:

 

  1. func New() LibraryInterface {    ...} 

在上面的 case 中,返回一個 interface 使 struct 的特性在庫里被隱藏了。實際上應該這么寫:

 

  1. func New() *LibraryStruct { ...} 

在庫里不應該存在接口的聲明,除非它被用在某個函數參數中。如果出現上面的 case,你就應該想想你在寫這個庫的時候的約定。當返回一個 interface 時,你基本上得聲明一系列可用的方法。如果有人想用這個接口來實現他們自己的功能(比如說為了測試),他得打亂他們的代碼來添加更多的方法。這意味著盡管在 struct 里添加方法是安全的,但在 interface 里不是。這個想法在這篇文章中被總結得很好《Accept Interfaces Return Struct in Go[2]》。這個方案也能解決配置的問題。你想修改庫中的一些特性,你可以簡單的修改 struct 中一些公開的字段。但是如果你的庫只提供給用戶一個 interface,這就玩不轉了。

使用配置結構體來避免修改你的APIs

另一種配置方法是在你的工廠函數中接收一個配置結構體,而不是直接傳配置參數。你可以很隨意的添加新的參數而不用破壞現有的 API。你只需要做一件事情,在Config結構體中添加一個新的字段,并且確保不會影響它原本的特性。

 

  1. func New(config Config) *LibraryStruct {    ...} 

下面是一種添加結構體字段的正確的場景,如果一個用戶初始化結構體的時候忘了添加字段名,這是一種我認為修改他們的代碼能得到原諒的場景。為了維護兼容性,你應該在你的代碼中用 person{name: "Alice", age: 30} 而不是 person{"Alice", 30}。

你能在 golang.org/x/crypto[4] 包里看到對上面的補充。總之,對配置來說,我認為允許用戶在返回的結構體里設置不同的參數是一個更好的方法,并且只在編寫復雜方法時才使用這種特定方法。

總結

根據經驗來講,在寫一個庫的時候,你應該總是允許用戶指定他們自己的 http.Client來執行 HTTP 調用。而且考慮到未來迭代修改帶來的影響,你可以嘗試用可擴展的方式編寫代碼。避免全局變量,庫不能存儲全局狀態。如果你有任何疑問-參考標準庫是怎么寫的。

我認為有一個很好的想法,在你的程序中用你的庫來測試并問自己一些問題:

  • 如果你嘗試多次引入庫會發生什么?
  • 你的庫有沒有單元測試?
  • 在不破壞原有代碼的前提下,有沒有一種非侵入式的方式來擴展你的庫?
  • 在不破壞原有代碼的前提下,是否可以添加額外配置參數?

 

責任編輯:華軒 來源: 今日頭條
相關推薦

2020-02-11 09:41:02

Go語言程序員文章

2021-03-01 21:59:25

編程語言GoCX

2021-03-01 18:35:18

Go語言虛擬機

2023-04-02 23:13:07

Go語言bufio

2022-10-17 09:08:01

2024-08-22 08:50:51

2025-02-11 09:01:57

2011-02-25 10:12:09

GoWeb

2014-02-18 11:24:07

云計算PaaS

2023-02-13 00:24:37

Go語言日志庫

2023-06-07 17:46:32

AI高考

2016-09-27 21:25:08

Go語言Ken Thompso

2024-05-07 08:46:06

GoGoogle云原生

2021-02-03 20:20:34

ReacHook數據

2014-01-14 09:10:53

GoHTTP內存泄漏

2022-10-21 09:23:31

腦累計算深度學習

2010-03-26 13:15:28

Python嵌入c

2019-07-19 15:42:57

Hadoop大數據YuniKorn

2023-06-30 08:23:36

Spring!SolonJavalin

2015-07-23 11:49:31

程序猿
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: av中文字幕在线观看 | 色婷婷亚洲国产女人的天堂 | 天堂网avav| 国产欧美精品 | 欧美一级视频免费看 | www亚洲一区 | 久久久久久成人 | 精品久久久久久亚洲精品 | 精品成人av | 97色伦网 | 亚洲成人一区二区三区 | 一二三区视频 | 中文字幕日本一区二区 | 91麻豆精品国产91久久久久久 | 激情网站在线观看 | 国产欧美一区二区在线观看 | 国产三级精品三级在线观看四季网 | 国产激情在线 | 国产视频1区 | 国产精品免费看 | 亚洲国产区 | 成人精品高清 | 欧美成人精品一区二区男人看 | 91免费版在线| 日韩精品在线观看一区二区 | 久久久av中文字幕 | 成人在线欧美 | 在线看中文字幕 | 亚洲精品在线免费观看视频 | 91精品福利 | 9porny九色视频自拍 | 一区二区中文字幕 | 久久久久久久电影 | 国产精品999| 国产激情视频网址 | 久久伊人一区二区 | av网站在线免费观看 | 国产1区2区3区 | 亚洲一区视频在线播放 | 欧美激情久久久 | 精品日韩一区二区 |