K8s源码风格及规范

###K8s源码风格及规范

一、工程概述

  • 本项目主要基于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:    "[email protected]",
}
  • 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

猜你喜欢

转载自www.cnblogs.com/tangxin2019/p/11615739.html
k8s