![](https://img-blog.csdnimg.cn/20210303225854717.jpg?x-oss-process=image/resize,m_fixed,h_224,w_224)
Uber技术研究
主要是Uber的golang技术学习研究
DreamCatcher
热爱编程,不仅仅是为了工作,而是爱好。
热爱生活,不仅仅是为了生存,而是责任。
热爱运动,不仅仅是为了健康,而是习惯。
沉迷太极拳,每天早上5点50起床,练四十分钟拳,四年内风雨无阻。
岁月流程,不再年轻,在这浮躁的社会和超强的生活压力下,希望在编程的道路上,能够坚持下去。
展开
-
Git 指定版本克隆
git clone -b v0.20.0 --depth=1 https://github.com/uber/cadence.git-b 后面写上指定 版本标签 , 即 tag, 比如 v0.20.0--depth 表示克隆深度, 1 表示只克隆最新的版本. 如果项目迭代的版本很多, 克隆会很慢原创 2021-04-18 12:19:00 · 1373 阅读 · 0 评论 -
Uber Go 语言编程规范:Linting
我们建议至少使用以下的linters,因为我们认为它们有助于发现最常见的问题,并且在没有不必要的规定的情况下为代码质量建立一个高标准:errcheckto ensure that errors are handled goimportsto format code and manage imports golintto point out common style mistakes govetto analyze code for common mistakes staticcheck...原创 2021-03-13 18:24:13 · 194 阅读 · 0 评论 -
Uber Go 语言编程规范:功能选项
函数选项是一种模式,在这种模式中,您声明一个不透明的Option类型,该类型在某些内部结构中记录信息。您接受这些选项的可变数量,并根据内部结构上的选项记录的完整信息进行操作。在构造函数和其他您认为需要扩展的公共api中,使用此模式的可选参数,特别是当您已经在这些函数上有三个或更多的参数时。Bad// package dbfunc Open( addr string, cache bool, logger *zap.Logger) (*Connection, error) ..原创 2021-03-13 18:13:29 · 143 阅读 · 0 评论 -
Uber Go 语言编程规范:表格驱动测试
请使用带subtests的表格驱动测试,以避免在核心测试逻辑重复时额外的写很多重复的测试代码。Bad// func TestSplitHostPort(t *testing.T)host, port, err := net.SplitHostPort("192.0.2.0:8000")require.NoError(t, err)assert.Equal(t, "192.0.2.0", host)assert.Equal(t, "8000", port)host, port, e..原创 2021-03-13 17:37:41 · 132 阅读 · 0 评论 -
Uber Go 语言编程规范:命名Printf 样式的函数
当声明一个printf样式的函数时,确保go vet工具能够检测到它并检查格式字符串。这意味着,如果可能的话,您应该使用预定义的printf风格的函数名。go vet会默认进行检查。请查询Printf family得到更多的信息。如果不能使用预定义的名称,则您选择的函数名称要以f 结尾:Wrapf, 而不是Wrap。go vet 可以检查特定的printf样式的名称,但它们必须以f结尾。$ go vet -printfuncs=wrapf,statusf另外,请参阅go vet: Pri.原创 2021-03-13 17:04:06 · 98 阅读 · 0 评论 -
Uber Go 语言编程规范:在Printf之外格式化字符串
如果要为Printf-style 样式的函数声明格式字符串,请将格式化字符串放在外面,并将其设置为const常量。这有助于go vet对格式字符串执行静态分析。Badmsg := "unexpected values %v, %v\n"fmt.Printf(msg, 1, 2)Good const msg = "unexpected values %v, %v\n"fmt.Printf(msg, 1, 2)...原创 2021-03-13 16:50:08 · 86 阅读 · 0 评论 -
Uber Go 语言编程规范:初始化 Maps
对于空的 maps,请使用make(..)初始化,并且以编程的方式填充的。这使得map的初始化在表现上不同于声明,并且可以方便地在以后添加容量大小提示(如果有的话)。Badvar ( // m1 可以安全的读写 // m2 在写时会panic m1 = map[T1]T2{} m2 map[T1]T2)//声明和初始化看起来非常相似Goodvar ( // m1 可以安全的读写 // m2 写时会panic m1 = make(map[T1]T2)原创 2021-03-13 16:18:54 · 89 阅读 · 0 评论 -
Uber Go 语言编程规范:初始化 Struct 引用
在初始化struct引用时,使用&T{}代替new(T),以便与struc的t初始化保持一致。Badsval := T{Name: "foo"}// inconsistentsptr := new(T)sptr.Name = "bar"Goodsval := T{Name: "foo"}sptr := &T{Name: "bar"}原创 2021-03-13 15:54:49 · 78 阅读 · 0 评论 -
Uber Go 语言编程规范:使用原生字符串字面值避免转义
Go支持raw string literals(" ` " 来表示原生字符串), 可以跨越多行并包含引号,使用这些可以避免手动转义的字符串,因为后者更难阅读。BadwantError := "unknown name:\"test\""GoodwantError := `unknown error:"test"`...原创 2021-03-13 15:45:23 · 756 阅读 · 0 评论 -
Uber Go 语言编程规范:避免语义不明确的参数(Naked Parameters)
函数调用中的意义不明确的参数(Naked parameters)可能会影响可读性,当参数名称的含义不明显时,请为参数添加 C 样式注释 (/* ... */)Bad// func printInfo(name string, isLocal, done bool)printInfo("foo", true, true)Good// func printInfo(name string, isLocal, done bool)printInfo("foo", true /* is.原创 2021-03-12 19:01:27 · 106 阅读 · 2 评论 -
Uber Go 语言编程规范:缩小变量作用域范围
如果有可能,尽量缩小变量作用域的范围。除非它与Reduce Nesting的规则冲突。Baderr := ioutil.WriteFile(name, data, 0644)if err != nil { return err}Goodif err := ioutil.WriteFile(name, data, 0644); err != nil { return err}如果你想要在if语句的作用域范围之外,需要一个函数调用的结果,那么你不应该尝试缩小作用域的范围。.原创 2021-03-12 17:58:56 · 155 阅读 · 0 评论 -
Uber Go 语言编程规范:nil 是一个有效的 slice
nil是一个长度为0的有效的slice。这意味着:您不应该显式地返回一个长度为0的slice,应该返回 nil。Badif x == "" { return []int{}}Goodif x == "" { //要返回nil return nil}要检查一个slice是否是空empty的,请始终使用len(s) == 0,而不是去检查是否为nilBadfunc isEmpty(s []string) bool { // nil 的 slice 也是有效..原创 2021-03-12 17:32:32 · 120 阅读 · 0 评论 -
Uber Go 语言编程规范:局部变量声明
如果显式地将变量设置为某个值时,则应该使用短变量声明(:=)。Badvar s = "foo"Goods := "foo"但是,在某些情况下,当使用var关键字时,默认值会更清晰。例如:Declaring Empty Slices,Badfunc f(list []int) { filtered := []int{} for _, v := range list { if v > 10 { filtered = append(filtere原创 2021-03-12 17:05:44 · 75 阅读 · 0 评论 -
Uber Go 语言编程规范:使用字段名来初始化结构体
在初始化结构体时,几乎总是应该指定字段名。现在已由go vet强制执行。Badk := User{"John", "Doe", true}Goodk := User{ FirstName: "John", LastName: "Doe", Admin: true,}例外情况:当测试表中有3个或更少的字段时,可以省略字段名。tests := []struct{ op Operation want string}{ {Add, "add"原创 2021-03-12 14:24:06 · 108 阅读 · 0 评论 -
Uber Go 语言编程规范:结构体中的嵌入
嵌入类型(比如互斥锁)应该位于结构体的字段列表的顶部(第一个),并且嵌入字段和常规字段之间必须有一个空行予以区分。Badtype Client struct { version int http.Client}Goodtype Client struct { //嵌入类型位于结构体字段列表的顶部 http.Client //空行分割 version int}嵌入应该提供切实的好处,比如以语义合适的方式添加或扩充功能。这样做应该不会对用户产生不利影响(另外原创 2021-03-12 14:23:46 · 115 阅读 · 0 评论 -
Uber Go 语言编程规范:请在未导出的全局变量前加上_
在未导出的顶层变量和常量前面加上_,以便在使用它们时清楚地表明它们是全局的标识符。异常:未导出的错误值,应该以err作为前缀。基本原理:顶层变量和常量有一个包的作用域。使用通用名称很容易在不同的文件中意外地使用错误的值。Bad// foo.go//这两个常量拥有包级作用域const ( defaultPort = 8080 defaultUser = "user")// bar.gofunc Bar() { //这个文件中,把默认端口给改掉了 defaultP原创 2021-03-11 15:25:40 · 199 阅读 · 0 评论 -
Uber Go 语言编程规范:顶层变量声明
在顶层,请使用标准的var关键字。不要指定类型,除非它与右侧的表达式不是同一类型。Bad// F()返回的是string类型,var 定义的变量也是string类型var _s string = F()func F() string { return "A" }Good//首先,希望变量 _s 的类型是 stringvar _s = F()// 既然F已经声明它返回一个string,因此我们没有必要再指定变量 _s 的类型了 func F() string { return原创 2021-03-11 15:13:44 · 113 阅读 · 0 评论 -
Uber Go 语言编程规范:不必要的else
如果一个变量,在If的两个分支中都设置了,则可以用一个If替换它。Badvar a intif b { a = 100} else { a = 10}Good//先给初始值a := 10//一个if分支判断if b { a = 100}原创 2021-03-11 14:41:50 · 73 阅读 · 0 评论 -
Uber Go 语言编程规范:减少嵌套
代码应该尽可能地减少嵌套,首先处理错误情况/特殊条件,并提前返回或继续循环。减少多层嵌套的代码数量。Badfor _, v := range data { //多层 if/else 循环嵌套 if v.F1 == 1 { v = process(v) if err := v.Call(); err == nil { v.Send() } else { return err } } else { log.Printf("I原创 2021-03-11 14:26:14 · 97 阅读 · 0 评论 -
Uber Go 语言编程规范:函数的分组与顺序
函数应该按照粗略的调用顺序排序 一个文件中的函数应该按照接收器分组因此,导出的函数应该先出现在一个文件中,struct,const,var定义之后。类型定义之后,可能会出现一个newXYZ()/NewXYZ()函数,但是在接收器的其他方法之前。由于函数是按接收器分组的,普通工具函数应该出现在文件的末尾。Badfunc (s *something) Cost() { return calcCost(s.weights)}type something struct{ ... ..原创 2021-03-11 14:18:03 · 126 阅读 · 0 评论 -
Uber Go 语言编程规范:导入别名
如果包名称不能与导入路径的最后一个元素匹配的话,则必须使用导入别名import ( "net/http" client "example.com/client-go" trace "example.com/trace/v2")在所有其他场景中,应该避免导入别名,除非导入之间有直接冲突Badimport ( "fmt" "os" nettrace "golang.net/x/trace" //此处,应该避免使用导入别名)Goodimport (原创 2021-03-11 12:57:32 · 169 阅读 · 0 评论 -
Uber Go 语言编程规范:函数名称
我们遵循 Go 社区关于使用MixedCaps for function names的约定,有一个例外是针对测试函数,它可能包含下划线,用于分组相关的测试用例,例如:TestMyFunction_WhatIsBeingTested原创 2021-03-11 11:32:21 · 55 阅读 · 0 评论 -
Uber Go 语言编程规范:包名称
当命名包的时候,根据以下的规则来命名一个名称:全部小写。不要使用大写或下划线。 大多数使用命名导入的情况下,不需要重命名。 简短而简洁。请记住,在每个使用的地方都用全名标识。 不要复数。例如,net/url, 而不要net/urls. 不要用"common", "util", "shared", 或者"lib".这是不好的,因此此名称不提供充足信息的。另外请参阅Package Names和Style guideline for Go packages....原创 2021-03-11 11:27:10 · 100 阅读 · 0 评论 -
Uber Go 语言编程规范:import 分组顺序
应该有两个导入组:标准库 其他库默认情况下,这是goimports设置的分组:Badimport ( "fmt" "os" "go.uber.org/atomic" "golang.org/x/sync/errgroup")Goodimport ( "fmt" "os" "go.uber.org/atomic" "golang.org/x/sync/errgroup")...原创 2021-03-11 10:58:04 · 464 阅读 · 0 评论 -
Uber Go 语言编程规范:将相似的声明分组
Go支持将相似的声明进行分组。Badimport "a"import "b"Goodimport ( "a" "b")同样适用于常量、变量、和类型声明Badconst a = 1const b = 2var a = 1var b = 2type Area float64type Volume float64Goodconst ( a = 1 b = 2)var ( a = 1 b = 2)type (.原创 2021-03-11 10:36:10 · 66 阅读 · 0 评论 -
Uber Go 语言编程规范:规范 一致性
本文中概述的一些准则可以被客观地评价;其他的,则是有场景的、上下文环境的或主观的。最重要的一点,是保持一致性。一致性的代码更容易维护,更容易优化,需要更少的学习成本,并且随着新约定的出现或bug类的修复,更容易迁移或更新。相反,在一个代码库中有多种不同或冲突的风格会导致维护成本升高、不确定性和认知偏差,所有这些都会直接导致开发效率降低、代码审查繁杂和Bugs。当将这些指导方针应用到代码库时,建议在包(或更大的)级别上进行更改:子包级别的应用程序在同一代码中引入多种样式,则违反了上述关注点。原创 2021-03-10 23:25:11 · 191 阅读 · 0 评论 -
Uber Go 语言编程规范:最好指定容器的容量
在可能的情况下指定容器容量,以便预先为容器分配内存。这将在添加元素时,最小化后续分配(通过复制和调整容器大小)。指定Map容器提示在尽可能的情况下,在使用make()初始化的时候提供容量信息make(map[T1]T2, hint)为make()提供容量提示,试图在初始化时调整映射的大小,这减少了在元素添加到map时,增长map和分配的需要.注意,与slices不同。map capacity提示并不保证完全的抢占式分配,而是用于估计所需的hashmap bucket的数量。 因此,..原创 2021-03-09 23:30:22 · 127 阅读 · 0 评论 -
Uber Go 语言编程规范:避免字符串到字节的转换
不要重复从固定字符串创建字节切片。相反,只执行一次转换并捕获结果。Badfor i := 0; i < b.N; i++ { w.Write([]byte("Hello world"))}// BenchmarkBad-4 50000000 22.2 ns/opGooddata := []byte("Hello world")for i := 0; i < b.N; i++ { w.Write(data)}// BenchmarkGood-4原创 2021-03-09 23:06:13 · 63 阅读 · 0 评论 -
Uber Go 语言编程规范:优先使用 strconv 而不是 fmt
在基础类型和string类型相互转换的时候,strconv比fmt 快。Badfor i := 0; i < b.N; i++ { s := fmt.Sprint(rand.Int())}// BenchmarkFmtSprint-4 143 ns/op 2 allocs/opGoodfor i := 0; i < b.N; i++ { s := strconv.Itoa(rand.Int())}// BenchmarkStrconv-4 .原创 2021-03-09 22:39:58 · 138 阅读 · 0 评论 -
Uber Go 语言编程规范:append的时候请优先指定切片容量
在尽可能的情况下,在初始化要追加的切片时,为make()提供一个容量值。Badfor n := 0; n < b.N; n++ { data := make([]int, 0) for k := 0; k < size; k++{ data = append(data, k) }}// BenchmarkBad-4 100000000 2.48sGoodfor n := 0; n < b.N; n++ { //指定容量 .原创 2021-03-09 21:55:22 · 93 阅读 · 0 评论 -
Uber Go 语言编程规范:避免调用init()方法
尽可能的避免调用init()方法,当init()是不可避免或必需的时候,代码应该尝试做如下建议:不管是程序的环境还是调用,必须是完全确定的。 避免依赖其他init()函数的调用顺序或副作用,虽然init()函数是顺序调用是众所周知的,但代码可能会发生变化,因此init()函数之间的关系可能会使代码变得脆弱且容易出错。 避免访问或操纵全局状态或环境状态,例如:服务器信息、环境变量、工作目录、程序参数/输入等。 避免I/O,包括文件系统、网络和系统调用。不能满足这些需求的代码可能属于一个辅助函数,作原创 2021-03-09 21:47:24 · 572 阅读 · 0 评论 -
Uber Go 语言编程规范:避免使用内置的名称
Go语言的language specification中概括了几个内置的、predeclared identifiers(预声明的标识符),这些标识符不应该在Go程序中再次用作名称。依赖于上下文,重新将这些标识符用做名称,将会遮盖原始标识符在当前的词法作用域(以及任何嵌套作用域)或者混淆代码,影响正常的代码逻辑。最好的情况是,编译器将会报错。最坏的情况是,这样的代码可能会引起潜在的、难以捕捉的bug。Badvar error string// `error` 覆盖了内建的error词..原创 2021-03-09 17:38:21 · 100 阅读 · 0 评论 -
Uber Go 语言编程规范:避免在公共结构体中嵌入类型
这些嵌入的类型会 泄露实现细节,阻止类型演变,并模糊文档。假设您已经使用一个共享的AbstractList,实现了各种列表类型,避免在具体的列表实现中嵌入AbstractList,相反的,只手写那些将会委托给抽象列表的具体列表中的方法。type AbstractList struct {}//以下是定义公共结构体的方法// Add adds an entity to the list.func (l *AbstractList) Add(e Entity) { // ...}/原创 2021-03-09 15:47:35 · 162 阅读 · 2 评论 -
Uber Go 语言编程规范:避免可变的全局变量
避免改变全局变量,而要选择依赖注入。这适用于函数指针以及其他类型的值。Bad// sign.go//直接定义一个全局变量var _timeNow = time.Nowfunc sign(msg string) string { now := _timeNow() return signWithTime(msg, now)}// sign_test.gofunc TestSign(t *testing.T) { oldTimeNow := _timeNow //更原创 2021-03-09 10:49:17 · 367 阅读 · 0 评论 -
Uber Go 语言编程规范:使用 go.uber.org/atomic
通过sync/atomic包的原子操作对原始类型s(int32,int64, etc.) 进行操作的时候,很容易忘记在对变量进行读取和修改的时候,使用原子操作。而go.uber.org/atomic包通过隐藏基础类型对这些操作增加了类型安全,另外,它还包括了一个方便的atomic.Bool类型。Badtype foo struct { running int32 // 原子类型}func (f* foo) start() { //原子操作 if atomic.Swap..原创 2021-03-09 10:16:41 · 1618 阅读 · 0 评论 -
Uber Go 语言编程规范:不要panic
运行在生产环境中的代码必须避免panics。Panics 是cascading failures级联失败的主要根源。如果有错误发生,函数必须返回一个错误并且允许调用者决定如何处理它。Badfunc run(args []string) { if len(args) == 0 { //直接panic了 panic("an argument is required") } // ...}func main() { run(os.Args[1:])}Goo..原创 2021-03-08 23:03:42 · 189 阅读 · 0 评论 -
Uber Go 语言编程规范:处理类型断言失败
type assertion的单个返回值形式针对错误的类型时将会产生 panic。因此,请一直使用“ comma ok ”的习惯用法。Badt := i.(string)Goodt, ok := i.(string)if !ok { // 优雅的处理错误}原创 2021-03-08 22:40:55 · 136 阅读 · 0 评论 -
Uber Go 语言编程规范:错误包装
如果一个函数或方法调用失败时,有三种方式来传播错误:如果没有额外的上下文环境需要添加并且你想保持原始的错误类型的话,请返回原始的错误。 通过"pkg/errors".Wrap添加上下文环境,以至于错误消息能够提供更多的上下文信息,并且"pkg/errors".Cause可以用来提取原始的错误。 如果调用者无需断言和处理指定的错误的情况下,请使用fmt.Errorf强烈建议在可能的情况下,请添加上下文,这样就不会出现“connection refused”这样模糊的错误,你会得到更多有用的错误描述信原创 2021-03-08 22:21:04 · 203 阅读 · 0 评论 -
Uber Go 语言编程规范:错误类型
在Golang中有多种声明错误的方式:errors.New 对于简单的静态字符串的错误 fmt.Errorf 用于格式化的错误字符串 实现 Error() 方法的自定义错误类型 用 "pkg/errors".Wrap 的 包装错误当返回错误时,请考虑以下内容以确定最佳选择:如果是一个简单的错误并且不需要额外的信息,那么errors.New就可以满足。 如果客户端需要检测并且处理错误,那么你需要自定义一个错误类型,并且实现Error()方法。 如果你需要传播下游函数返回的错误,那么你需..原创 2021-03-08 18:20:32 · 195 阅读 · 0 评论 -
Uber Go 语言编程规范:使用time处理时间
时间处理是很复杂的。关于时间的错误的假设通常包括以下几个方面:一天有 24 小时 一小时有 60 分钟 一周有七天 一年 365 天 还有更多例如,1表示在一个时间点上加上24小时,并不总能产生一个新的日历日期。因此, 在处理时间时,始终使用"time"包,因为它有助于以更安全、更精确的方式处理这些错误的假设。使用time.Time表达瞬时时间处理瞬时时间时请使用time.Time,在比较、添加和减少时间时使用time.Time中的方法。Badfunc isAct...原创 2021-03-07 17:18:17 · 162 阅读 · 0 评论