使用Go語言框架進行web開發筆記

最近須要用Instagram的api抓取其用戶的圖片,因爲須要用oauth2驗證, 因此應用必須包含一個web界面。設想可以實時返回下載數量,因此用websocket。還有須要考慮到效率問題,綜合以上幾點,想用一門語言開發的話,最終選擇用golang進行開發,node的回調實在不喜歡。php

前言

關於golang的web開發有很多框架,例如 martini, gin, revel,gorilla等。 以前玩過revel,感受封裝的太多了,做爲一個小應用不須要這麼複雜,並且google獲得結果是revel的效率相對較差。gin的benchmark顯示效率是martini的40倍,可是gin比較新因此他的的生態圈相對較少。最終選擇了martini, 有不少middleware能夠選擇,其中就包括了websocket,而且背後用的是gorilla websocket這個包。前端

界面和功能

  1. 一個跳轉到Oauth2登錄受權頁面的連接node

  2. 受權完成後,跳回服務的頁面,此時得到了access_token, 就能夠隨心所欲了。所有的功能也都集中在這個頁面,最終的界面以下圖所示。laravel

界面和功能

點擊鏈接是用來打開websocket鏈接的。開始發送數據是開始把用戶ID發給服務端,服務端調用api開始抓取圖片。中止用於中止本次的抓取服務。已完成數量用於實時返回抓取的圖片數量。golang

程序大體結構

程序大體結構

這裏把Jobs, goroutine #1, #2等做用在全局是爲了在websocket斷開後,下載還能繼續執行。websocket goroutine是鏈接創建後的做用域,鏈接斷開後這個goroutine就不存在了。Jobs, NextUrl充當隊列的角色。 Done的做用僅僅是計數。這裏少寫了兩個全局變量,Quit chan int, IsPreparing bool, 這兩個變量是用來讓前端控制抓取程序是否進行的。web

簡單理解就是一個產生任務的for循環,一個消費任務的for循環,一個用於給client返回計數的for循環。這裏不得不感嘆,goroutine channel的設計使得編碼簡單明瞭。sql

遇到的問題

因爲第一次正經使用Go,仍是遇到很多問題的。不過需求比較簡單,因此沒有接觸什麼深刻的內容。主要集中在強類型帶來的問題。json

DB查詢

以前寫過一篇關於database/sql的文章,此次直接用了sqlx這個庫,能夠少寫很多代碼,也少犯錯誤。可是畢竟不如laravel那麼方便,所幸須要寫的sql很少,臨時寫幾個方法就搞定。同時思考,如何實現一個eloquent的api。貌似有難度。小程序

Json處理

強類型決定了Json的處理是個痛。以前寫過一個天氣預報的小程序,用的是map[string]*json.RawMessage 這種映射結構,而後一層一層解開json。當時沒發現這是有問題的,由於若是用RawMessage, 字符串的引號"也會被保留,使得字符串結果先後多了引號。
此次再次google了一次,發現仍是得用map[string]interface{}來映射,而後再用type assertion來一層層的解開json。這是一個痛苦的過程,想起php中的json_decode()不由淚流滿面。segmentfault

Stop Goroutine

如何中斷一個goroutine是一個問題,由於須要控制開始中止。谷歌一下很快就有結果。

go func() {
        for {
            select {
            case <-Quit:
                IsPreparingJobs = false
                return
            default:
                // to do something
            }

        }
    }()

這裏設置一個IsPreparingJobs是用於中斷後再次開始這個循環。

Testing

Golang提供的測試工具很是方便,go test就能進行全部測試。從martini源碼中複製了兩個經常使用方法出來。

func expect(t *testing.T, a interface{}, b interface{}) {
    if a != b {
        t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
    }
}

func refute(t *testing.T, a interface{}, b interface{}) {
    if a == b {
        t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
    }
}

總結

感受golang做爲web開發工具,在數據格式處理方面,沒有弱類型語言方便。這點node卻是很是好,json轉object很是方便。也許配合Promise,node會比較好用吧。golang也有優點,goroutine很是好用,官方的庫功能很是全,打包爲二進制可執行文件使得部署異常容易,強類型語言效率比較高。

最後有感於前幾天的shadowsockets事件,做爲一個ss使用者,除了感謝無私的開發者,剩下的就只是憤怒和失望。昨天又看了老羅的T1發佈會,Born to be proud, 天生驕傲,在堅持作人原則方面,老羅一直是個人楷模。期待今晚的錘子發佈會。

相關文章
相關標籤/搜索