2012年10月31日 星期三

[Go筆記] Heroku, Facebook

最近給自己一個作業寫了一個Go版的Facebook API, 本想要實作realtime api時想到, 我需要把這server開放給Facebook server可以存取

看來看去, 好像只有Google自家的GAE有支援Go, 這大概也是因為Go是他們親生子的關係吧, 不過之前一陣子用Heroku用習慣了, 而且, 想說Heroku有支援那麼多的語言平台, 不知道有沒有, 結果翻遍官方的文件, 卻沒發現Go的蹤影

正當要放棄時, 發現, 其實Heroku還蠻威的, 除了支援很多不同的語言平台外, 居然還可以讓你延伸, 而它就是透過開放"Buildpack"這東西:



而就有一個老兄寫了一個Go用的buildpack (這位老兄在Heroku工作):


基本上就是建立Procfile和.godir而已, 很簡單, 這樣地鼠同好就有除了GAE以外的選擇囉....

另外就是自己的作業, Facebook API for Go : https://github.com/julianshen/FacebookGoSDK
這是一個api實作可以用於server端, realtime API目前還寫的很簡陋, 詳細用法可以看 sample/server.go

這邊一個比較好玩的是, 在Go裡, 你要用這樣的package, 毋須把整個source抓回來build, 而只要使用這樣的方法import:

import facebook "github.com/julianshen/FacebookGoSDK"
這樣是import一個在github上的package, 當你使用"go run"或"go get"之類的來編譯執行程式時, Go自動會上github幫你把這些相關的package取回, 用這個Heroku buildpack做出的環境一樣適用

第一次用impress.js做的投影片: Introduction to node.js

明天要在team內開一堂node.js簡介的課, 每次老是用Powerpoint和keynote做投影片, 開始有點乏味了, 所以這次打算嘗試一下

Impress.js

這跟一般投影片製作軟體很不一樣, 正確說來它是一個javascript framework而非一個完整的軟體, 所以也沒啥GUI(似乎也有不少人幫它寫editor), 不過基本說來, 用它來做投影片的方式, 就是拿source codes裡的html檔來改就對了

出來的結果很炫, 但編寫的過程有點小累, 所以後面有點偷懶, 不過也完成了明天要講的投影片:

Introduction to node.js

寫完了之後, 想把它開放出來, 我之前放投影片都依賴了slideshare, 不過slideshare並不能吃這種檔案呀! 所以host又是另一個問題, 所幸, 還有developer的好朋友 - github

github有個好東西叫page, 可以讓你放一些介紹網頁, 也可以有自己的host name像是"julianshen.github.com", 只要照下面這網頁內的說明, 就可以建立屬於自己project的"page":

Creating Project Pages manually

2012年10月24日 星期三

[Go筆記] Go on GAE: 比"Hello World"多一點點: 處理static files

今天被問到Go適合用在哪方面, 至今只看了Go兩個晚上的我, 實在很難回答這問題, 先從FAQ找來創立Go的目的說起:

"Go is an attempt to combine the ease of programming of an interpreted, dynamically typed language with the efficiency and safety of a statically typed, compiled language. It also aims to be modern, with support for networked and multicore computing. Finally, it is intended to be fast: it should take at most a few seconds to build a large executable on a single computer. To meet these goals required addressing a number of linguistic issues: an expressive but lightweight type system; concurrency and garbage collection; rigid dependency specification; and so on. These cannot be addressed well by libraries or tools; a new language was called for."
簡而言之, Go的目標是一個簡單又有效率的語言, 加上一開始設計就考慮網路以及多核, 就姑且說它適合server端的開發吧

事實上, GAE(Google AppEngine)也是有支援Go的 (怎麼說呢, 好歹這也是Google自己親生的呀)

那, 現在開發server端的工具那麼多種, 有什麼樣的理由是選Go優於其他解決方案呢? 以效率來說, 或許比較好吧, 既然它是原生碼, 應該會快一些吧, 但這也沒啥好的benchmark來佐證, 劣勢呢? 以node.js來相比好了(今年看比較多這個, 直覺拿這來做比較), 它不但沒既有的developer做基礎(既有的javascript developer是很大一群的), 也沒有數量很多且快速增長的第三方模組可供利用(雖然, 盲目用npm上的模組, 某種程度上要承擔一定的風險), 最大的問題就是...."文件"

以上前半段是抱怨文, 不過文件不足也沒辦法當啥藉口, 這年頭...."做就對了".....GAE上關於Go的文件也不是沒有, 跟著做, 就可以做出"Hello World"了, 但剛做完後, 突然楞住想....那...我的html檔案放哪裡? 我總不能每個文件都寫在程式內, 總會有靜態檔案的呀! 有點讓我回到十幾年前寫CGI的感覺

GAE的文件還真找不到, 但在Go的文件http.FileServer的範例可以找到解答, 但要把"FileServer"這個interface跟這件事聯想在一起還真有點不容易, 不過反正就是在程式內要加入下面這行來處理靜態檔案

http.Handle("/", http.FileServer(http.Dir("./static")))
這範例讓你可以把靜態檔案放在"static"目錄下, 假設你在static目錄下放一個a.html, 那這行的目的就是可以讓你用 http://your_app_host/a.html來存取它

我起始一個範例放在github上, 從這可以看完整的目錄結構, 未來相關範例也會放在這邊

2012年10月23日 星期二

[Go筆記] defer

Go沒有exception handling這樣的設計, 所以沒有像java裡的try{} catch{} finally{...}這種東西, 在java裡, 我們會用

try { 
     .....
} finally {  
    in.close();
}
在finally區塊內去做一些善後的工作, 以確保這些善後工作可以在程式執行後不管有沒錯誤發生都可以被執行到, 在Go中, 用的則是defer:


defer後面接的可以是一個closure, 這些closure會在函式執行結束後(return 之後)緊接著被執行, 所以這段程式執行的結果會是這樣:

6
b
e
c
nn
a
--------
1
b
e
a

[Go筆記] Do not communicate by sharing memory; instead, share memory by communicating.

Do not communicate by sharing memory; instead, share memory by communicating. 
這是在Go的concurrent programming裡一個很重要的精神, concurrent programming也是Go裡面一個相當重要的部份, 它已是語言本身的一部分

"channel" 也就是這精神下的產物, channel可以說是多個thread之間溝通的工具, 有點像是"pipe"但又有點肩負多執行緒間synchronization的責任, 下面實作了一個concurrent merge sort (我想這例子蠻適合的)



"go"這個修飾字用來啟用一個goroutines, goroutine可以視為一個輕量的執行緒(lightware thread), 在這用了一個內容是整數陣列的channel: chan []int, channel必須要先用"make"初始化

由於使用了"go MergeSort(data[:middle], leftChan)", 因此, 左右兩邊的merge sort是同時進行的, 直到兩邊都結束後才會執行"merge"的動作, 但用了"go"啟用了執行緒, 連續這兩行是不會卡住(block)等結果的, 那怎確定兩個執行緒都真的結束後才執行merge的動作? 這其中就是透過channel來做同步化的動作, "ldata := <-leftChan", 這一段是將leftChan這個channel的結果指定到ldata, 如果leftChan一直沒輸入(input)進來, 這一行就會等在這, 直到左邊的MergeSort執行到Merge結束後(r<-)

主程式也是叫起一個執行緒做MergeSort的動作, 等到結果產生才將結果印出, 整個不是很難懂, 但這思維還有點難調整(對我來說)

[Go筆記] Go語言中的Closure

我不太懂closure, 不懂的程度大概是我在用它的時候也沒有意識到我在用, 也沒玩過Go, 不過昨晚心血來潮的開始想用它來寫一些東西, 研究了一下, 發現它...挺有趣的, 尤其是concurrent的部份, 以及讓我重新檢視了一下closure這部份

在Go裡, function是可以像在javascript中一樣, 被指定到一個變數來使用:

上面兩個範例, 一個是把函式指定給一個變數, 一個是來當做回傳值, 這也是Go的closure大致上的形態, 在Go Tour的第48頁的作業, 便是要求利用closure來完成Fibonacci數列的計算, 我們所熟知的Fibonacci數列(0, 1, 1, 2, 3, 5, 8 ... f(n) = f(n-1) + f(n-2))可以用iterative或recursive的方式來求解(範例), 當然使用Go其實也可以採用這兩種方式:

Iterative solution:
Recursive solution:
如果單以公式看, Recursive solution是比較容易被理解的, 不過也比較有stack overflow的風險, 當然, 照這練習題的要求, 以上兩者都不滿足, 那改用closure來實作又是怎樣?
整體上還算蠻簡潔的, 既然closure在javascript也很常被利用, 這邊放一個javascript的版本做一下比較:

測試了一下效能, 前三種實作方式, 感覺不出有太大的差異, 也就很難說誰優誰劣, 至於Go與javascript的比較, 如果是以"go run "的方式跟node.js來比, node.js高出甚多, 可能"go run"還是需要經過編譯階段, 但如果先以"go build"編譯成原生碼(native code), go的效能就高出甚多了, 不過以這比較也不算準啦....


2012年10月8日 星期一

在node.js使用underscore.js

太早起床,只好隨便研究點東西 :P
 
underscore.js對javascript來說是一個蠻好用的工具, 在前端應用程式的開發中也很常被利用到,但同樣以javascript為基礎開發的node.js, 能否直接使用underscore.js呢?

嘗試以下面的程式碼用node.js跑:

require('./underscore.js');                                                                

var a = [1, 23, 6, 11, 25, 12, 33, 11, 4];
 
 _.forEach(a, function(v) {
     console.log(v);
});


執行結果會得到"ReferenceError: _ is not defined"
打開underscore.js的原始碼一看, 發現了這一段, 其實它是有針對node.js做手腳的:


// Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in
// the browser, add `_` as a global object via a string identifier,                     
// for Closure Compiler "advanced" mode.
if (typeof exports !== 'undefined') {
     if (typeof module !== 'undefined' && module.exports) {
       exports = module.exports = _;
     }
     exports._ = _;
 } else {
      root['_'] = _;
 } 

也就是, 在browser時, "_"是一個global object, 但在node.js則不是, 原本的範例如果改成這樣就可以了:


var _us = require('./underscore.js');                                                                

var a = [1, 23, 6, 11, 25, 12, 33, 11, 4];
 
 _us.forEach(a, function(v) {
     console.log(v);
});


這樣一來, 前後端也可以共用同一份underscore.js了

補充: 類似的工具還有async這個, 也是前後端都可以應用


----- 10/11 補充 -----
寫這篇的時候真的是沒睡飽, 沒注意看underscore放在github上的內容, 它已經弄好node module了, 所以只要:
npm install underscore
就可以裝好了, code裡面也只需要用"var _us = require('underscore')" 

2012年10月3日 星期三

一些小想法 10/4

趁著等車時寫一下昨天搭車時想到的一些東西

今年參加了好幾個國內外的hackthon,收穫還算不少,覺得,很多developers都有很多不錯且創新的想法,但實際上,大部份的工作場,除了以developers為主體的公司外,大部份的developers處的角色都是執行者,這些"想法"反而往往在工作場合不會出現或被埋沒,這讓我想到"Effective Programming"裡提到的"developers大多不善於表達"!

這倒很難辯駁的,這一行,包含我自己,不用說不懂的做美美的簡報、炫麗的demo,連把一個簡單的觀念傳達給別人都可能要花上大把時間,尤其是傳達給非技術相關的,developers的思考模式大多是非線性的、跳tone的,強一點的根本就是multi cores,而且,都是沒耐性的,所以往往傳達給別人的,大多不到本意的六成,被瞭解的大概又只剩這一半

Hackthon算是一種不錯的訓練,訓練人在短時間團隊合作並傳達更多有趣的想法,雖然我不是很喜歡那些藉這種場合宣傳自己產品的,畢竟他們的產物不是在當下產生的,不過也是很多有趣的startup就這麼興起的