三個小項目入門Go語言|位元組青訓營筆記

前言

這是青訓營的第一課,今天的課程比較快速的講解了go語言的入門,並配合三個小的項目實踐梳理所學知識點,這裡詳細回顧一下這三個項目,結合課後作業要求做一些程式碼補充,並附上自己的分析,青訓期間的所有課程筆記會同步文末公眾號,有需要同學請關注~。

項目倉庫地址://github.com/wangkechun/go-by-example

實戰

項目一:guessing-game

生成一個100以內隨機數,玩家在控制台輸入猜測的數字,程式會不斷回饋猜測的值與生產值的大小關係,直到玩家輸入正確,程式碼簡單,這裡直接貼出(需要注意不要忘記添加隨機數種子):

image-20220507183655438

項目二:simpledict

先概述一下功能:用戶將需要翻譯的單詞作為參數在命令行運行go的main函數,程式會返回翻譯結果。通過下面的語句可以直接運行樣例倉庫程式碼中的main函數,得到翻譯結果。

image-20220507184640950

那麼程式是如何實現這個翻譯功能的呢?它做了下面幾件事:

  • 獲取main函數運行時的參數hello作為需要翻譯的單詞(通過go的api獲取)

  • 請求翻譯軟體的api獲取結果數據:

    • 這個過程和爬蟲的工作比較像,模擬用戶在網頁上提交翻譯的請求,其本質上就是發送了一個http請求,攜帶需要翻譯的單詞資訊,響應翻譯結果的json並由瀏覽器解析,通過下圖的copy as cURL可以將本次request的請求以cURL請求的方式拷貝。

    image-20220507185726072

    • 訪問://curlconverter.com/#go,這個在線工具可以將curl命令轉換成go語言程式碼(或者其他語言),將得到的程式碼直接複製到goland中運行就可以實現用go程式碼模擬請求這個翻譯介面,得到響應數據(文本格式的json)

      image-20220507192208213

      image-20220507190940969

  • 解析結果數據

    • 此時得到的翻譯數據是文本格式的json(就是byte數組,或者說字元串),因此需要將其反序列化為go的結構體,然後列印出我們需要的翻譯資訊。

    • 訪問://oktools.net/json2go,這個在線工具可以將json轉go的struct,然後將這個結構放入go程式碼中,使用json包的Unmarshal函數將json字元串字元串反序列化為結構體,後面就可以列印結構體中需要的屬性(包含翻譯結果)

      image-20220507203251798

      image-20220507191114812

  • 改進:用到兩個翻譯軟體的介面,並且並發訪問,思路是一樣的,就是再找一個翻譯軟體的介面重複上面的操作,然後重點在於並發的實現,這裡啟用兩個goroutine,藉助sync包的WaitGroup,先初始化一個2的容量,然後在一個go程結束之後調用wg.Done(),只有全部容量次數的Done調用後wg.Wait()才會放行,否則任意一個go程未完成,主go程都不會繼續執行(但是如果沒有這個WaitGroup去限制,則在主go程結束時,因為由其創建的子go程可能並沒有完成,但依舊會結束,而恰恰因為並發的關係,編碼先後順序的失去了作用,發生這種情況的概率很高)

image-20220507192736383

項目三:proxy

實現一個簡易版的socks5的代理伺服器,代理的工作流程如下:

image-20220507194934754

  • 本質就是客戶端要先和代理伺服器建立TCP連接,然後socks代理伺服器和需要訪問的目標伺服器建立TCP連接,對於所有從客戶端發來的請求由代理伺服器轉發給目標伺服器,且目標伺服器的響應數據也由代理伺服器轉發給客戶端(socks5代理伺服器就是以sock5s協議為標準去建立客戶端和代理伺服器的通訊)

  • 觀察proxy項目包的v4版本(clone地址已經給出),看到代理服務端的process函數如下:

    image-20220507195958463

    • 代理的工作由auth()認證和connect()連接兩個部分組成,看一下最上面給出的代理工作流程圖,可以看到對應著協商階段和通訊階段。而我們發現,本實例的客戶端發起的是一條curl –socks5 127.0.0.1:1080 -v //www.qq.com,需要注意的細節是,auth和connect工作並不是一蹴而就的,它們從reader緩衝區讀取客戶端發送過來的數據,驗證之後返回給客戶端,然後再獲取從客戶端發送過來的數據,而客戶端的這部分工作已經被curl工具隱藏,而非只是發起了一次請求。
    • 因為auth和connect函數中多次使用到的從緩衝區讀取位元組的這個api在緩衝區沒有byte的時候,是會被阻塞的,因此會等待客戶端發送數據,因此只要代理伺服器遵守socks5協議規定的通訊規則進行解析客戶端的數據,發送指定的響應,而客戶端也遵守這個規則解析和發送數據(本例就是curl –socks5 xxx幫我們完成了),就可以實現socks5代理伺服器的工作模式
    • 因此我理解中的socks5代理伺服器就是完全在socks5協議約束的基礎上進行編碼的一個伺服器,之後的請求和響應轉發則和socks5沒關係了

結束語

對於第三個樣例這裡只是著重講了一下我的一些理解,socks5代理部分還有很多值得深入學習的地方。關於後面課程的學習,也盡量會保證筆記的輸出,歡迎各位一起探討學習~

關注微信公眾號【程式設計師白澤】,將同步更新位元組青訓營的學習筆記