天天看點

go-tour源碼閱讀下面先看下裡面的目錄從gotour/local.go看起下面就是使用http包做不同的路由了。先看goplay.go下面就看fmt.go

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包在這裡

直接在全局變量中寫了兩個參數http和html。

http說明是在哪個端口監聽。

html是說明是輸出html頁面還是打開,這個html是沒有用的,估計作者想做這個功能來着,還沒做完。

init函數是将編譯生成的可執行檔案存放的臨時檔案夾設定好。

進入main函數,有個uniq的chan int,這個是為了給臨時檔案做唯一标示的,會不斷增長的。

main中的uniq是一個id生成器,這個方法很常用

<code>var</code> <code>(</code>

<code>     </code><code>// a source of numbers, for naming temporary files</code>

<code>     </code><code>uniq = make(chan</code><code>int</code><code>)</code>

<code>)</code>

<code>func main() {</code>

<code>     </code><code>flag.parse()</code>

<code>     </code><code>// source of unique numbers</code>

<code>     </code><code>go func() {</code>

<code>          </code><code>for</code> <code>i := 0; ; i++ {</code>

<code>               </code><code>uniq &lt;- i</code>

<code>          </code><code>}</code>

<code>     </code><code>}()</code>

<code>}</code>

main中首先擷取go-tour的目錄,它是使用build包來擷取,可以學之當做固定模闆

<code>// find and serve the go tour files</code>

<code>p, err := build.default.import(basepkg,</code><code>""</code><code>, build.findonly)</code>

<code>if</code> <code>err != nil {</code>

<code>    </code><code>log.fatalf(</code><code>"couldn't find tour files: %v"</code><code>, err)</code>

<code>root := p.dir</code>

有幾個不同的路由器:

/ ,  /favicon.ico, /static/ , talk/,  kill

kill是殺死一個running的指令。這裡有個running是為了跑正在運作的程式

run函數很好的示範了如何運作系統指令,并且輸出結果

好了,這裡的main看完了,當你實際運作的時候你會發現,程式中對代碼的編譯實際上是使用/compile和/fmt兩種。這兩種通路路徑是在goplay.go和fmt.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這兩個檔案

對代碼進行格式化應該也可以使用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中)少即是極多!

繼續閱讀