一、工程概述
- 本項目主要基於Kubernetes集群開展,針對開源項目進行功能擴展。要求基於已有的Kubernetes集群和Prometheus 監控系統進行擴展開發。
- K8s是由Google開發,並使用go語言進行開發的。
二、源碼准備
1.系統環境:
- 操作系統:我們使用Linux作為k8s源碼分析和調試環境,fedora、centos、ubuntu都行,我這里使用fedora;
- golang相關:
GOROOT=/usr/local/lib/golang
GOPATH=/root/go
go version go1.10.3 linux/amd64
2.源碼下載
mkdir -p /root/go/src/k8s.io
cd /root/go/src/k8s.io/
git clone https://github.com/kubernetes/kubernetes.git
-
目錄展示:

-
主要目錄:
| 目錄名 | 功能 |
|---|---|
| cmd | 每個組件代碼入口(main函數) |
| pkg | 各個組件的具體功能實現 |
| staging | 已經分庫的項目 |
| vendor | 依賴 |
3.IDE
- 通過學校郵箱申請JetBrains的教育賬號,通過Goland看代碼:

三、go語言特點及命名規范
1.go語言特點
GO語言的關鍵特性主要包括以下幾方面:
- 並發與協程
- 基於消息傳遞的通信方式
- 豐富實用的內置數據類型
- 函數多返回值
- defer機制
- 反射(reflect)
- 高性能HTTP Server
- 工程管理
- 編程規范
2.相關規范
-
package名字
保持package的名字和目錄保持一致,盡量采取有意義的包名,簡短,有意義,盡量和標准庫不要沖突。 -
import 規范
import在多行的情況下,自動工具會自動幫你格式化,但是我們這里還是規范一下import的一些規范,如果你在一個文件里面引入了一個package,還是建議采用如下格式:
import (
"fmt"
)
如果你的包引入了三種類型的包,標准庫包,程序內部包,第三方包,建議采用如下方式進行組織你的包:
import (
"strings"
"myproject/models"
"myproject/controller"
"github.com/mysql"
)
有順序的引入包,不同的類型采用空格分離,第一種實標准庫,第二是項目包,第三是第三方包。在項目中不要使用相對路徑引入包:
// 這是不好的導入
import “../pkg”
// 這是正確的做法
import “github.com/tx23/pkg”
- 變量申明
變量名采用駝峰標准,不要使用_來命名變量名,多個變量申明放在一起
在函數外部申明必須使用var,不要采用:=,容易踩到變量的作用域的問題。
var (
Found bool
count int
)
- 自定義類型的string循環問題
如果自定義的類型定義了String方法,那么在打印的時候會產生隱藏的一些bug。
type MyInt int
func (m MyInt) String() string {
return fmt.Sprint(m) //BUG:死循環
}
func(m MyInt) String() string {
return fmt.Sprint(int(m)) //這是安全的,因為我們內部進行了類型轉換
}
- 避免返回命名的參數
如果你的函數很短小,少於10行代碼,那么可以使用,不然請直接使用類型,因為如果使用命名變量很容易引起隱藏的bug。
func Foo(a int, b int) (string, ok){
}
當然如果是有多個相同類型的參數返回,那么命名參數可能更清晰。
func (f *Foo) Location() (float64, float64, error)
-
錯誤處理
錯誤處理的原則就是不能丟棄任何有返回err的調用,不要采用_丟棄,必須全部處理。接收到錯誤,要么返回err,要么實在不行就panic,或者使用log記錄下來,error的信息不要采用大寫字母,盡量保持你的錯誤簡短,但是要足夠表達你的錯誤的意思。 -
注意閉包的調用
在循環中調用函數或者goroutine方法,一定要采用顯示的變量調用,不要再閉包函數里面調用循環的參數
fori:=0;i<limit;i++{
go func(){ DoSomething(i) }() //錯誤的做法
go func(i int){ DoSomething(i) }(i)//正確的做法
}
-
在邏輯處理中禁用panic
在main包中只有當實在不可運行的情況采用panic,例如文件無法打開,數據庫無法連接導致程序無法正常運行,但是對於其他的package對外的接口不能有panic,只能在包內采用。強烈建議在main包中使用log.Fatal來記錄錯誤,這樣就可以由log來結束程序。 -
struct規范
struct申明和初始化格式采用多行:
定義如下:
type User struct{
Username string
Email string
}
初始化如下:
u := User{
Username: "astaxie",
Email: "astaxie@gmail.com",
}
- recieved是值類型還是指針類型
到底是采用值類型還是指針類型主要參考如下原則:
func(w Win) Tally(playerPlayer)int //w不會有任何改變
func(w *Win) Tally(playerPlayer)int //w會改變數據
更多的請參考:
https://code.google.com/p/go-wiki/wiki/CodeReviewComments#Receiver_Type
- 帶mutex的struct必須是指針receivers
如果你定義的struct中帶有mutex,那么你的receivers必須是指針
參考資料:
https://code.google.com/p/go-wiki/wiki/CodeReviewComments
http://golang.org/doc/effective_go.html
