這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
go-tour是一個web項目,具有很強的可讀性。
下面先看下裡面的目錄
appengine:這個包是當你想把go-tour布置到GAE上的時候使用的安裝,我們這裡只是使用本地安裝,所以這裡的代碼可以不看
solutions:這個檔案夾可以忽略,只是對文檔中execise的答案,與go-tour網站無關
talks:這個是作者做的關於go-tour的演講放在這裡面,也可以直接忽略
static:這個檔案夾是存放靜態資源,js,css,html都是放在這裡面
tree:這個檔案夾存放程式自動產生一個樹的程式碼封裝。這個是具體的功能才使用到的,與網站無關
wc:測試套件。這個是具體的練習題中才使用的到,與網站無關
pic:對圖片的處理包。這個是具體的練習題中才使用到的,與網站無關
gotour:這個才是真正的go-tour的入口,main包在這裡
從gotour/local.go看起
直接在全域變數中寫了兩個參數http和html。
http說明是在哪個連接埠監聽。
html是說明是輸出html頁面還是開啟,這個html是沒有用的,估計作者想做這個功能來著,還沒做完。
init函數是將編譯產生的可執行檔存放的臨時檔案夾設定好。
進入main函數,有個uniq的chan int,這個是為了給臨時檔案做唯一標示的,會不斷增長的。
main中的uniq是一個id產生器,這個方法很常用
var ( // a source of numbers, for naming temporary files uniq = make(chan int))func main() { flag.Parse() // source of unique numbers go func() { for i := 0; ; i++ { uniq <- i } }()}
main中首先擷取go-tour的目錄,它是使用build包來擷取,可以學之當做固定模板
// find and serve the go tour files p, err := build.Default.Import(basePkg, "", build.FindOnly)if err != nil { log.Fatalf("Couldn't find tour files: %v", err)}root := p.Dir
下面就是使用http包做不同的路由了。
有幾個不同的路由器:
/ , /favicon.ico, /static/ , talk/, kill
kill是殺死一個running的命令。這裡有個running是為了跑正在啟動並執行程式
run函數很好的示範了如何運行系統命令,並且輸出結果
好了,這裡的main看完了,當你實際啟動並執行時候你會發現,程式中對代碼的編譯實際上是使用/compile和/fmt兩種。這兩種訪問路徑是在goplay.go和fmt.go中定義的
先看goplay.go
直接在init()中寫上了HandleFunc,這樣也能更醒目地告訴所有人,這裡的包是為了編譯使用
Compile函數中的具體實現步驟是用compile函數(local.go中)來實現的,後面就是json編碼後輸出。
下面看main中的compile,main中有維持一個running結構,這裡值得注意的是它使用的初始化直接在struct定義的時候加個var,這個可以記一下
var running struct {
sync.Mutex
cmd *exec.Cmd
}
繼續看compile,這個時候,參數request裡面是包含要啟動並執行go代碼
先將go代碼放到臨時檔案中,然後bin是目標組建檔案,src是源碼檔案
第一步,將代碼寫入到src中
第二步,運行go build,並使用-o 參數,將目標檔案產生到bin中
第三步,運行bin,輸出結果(當然這個結果是有做一些處理,之類的commentRe的作用)
第四步,刪除src和bin這兩個檔案
下面就看fmt.go
對代碼進行格式化應該也可以使用go fmt工具,但是這裡不是這樣使用的。
同goplay.go一樣,在init的時候設定了一個Handle
然後使用gofmt函數對代碼格式化,進到gofmt函數
gofmt函數使用了go/token,go/parser對代碼進行格式化,實際的工作就是:
1 順序化import包
2 美化go代碼
哈哈,這裡就是說go的程式能對自身(go程式)進行美化和運行(自舉),這個感覺太爽了,使用的就是go/XXX的包
這裡的幾個關鍵函數:
token.NewFileSet() : 建立fset結構
parser.ParseFile() : 解析go編碼(這步最後的mode能制定是解析到什麼地步)
ast.SortImports() : 將import包進行排序
printer.Fprint() : 美化工具
這下代碼就結束了,至於頁面上出現的分頁的效果等,都是js和css作用的結果,與伺服器無關了。
整個頁面只需要3個代碼檔案(靜態頁面除外)!300行代碼不到的量!(當然它更多的操作是在js中)少即是極多!