《Go语言精进之路》读书笔记 | 使用一致的变量声明形式
Posted COCOgsta
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Go语言精进之路》读书笔记 | 使用一致的变量声明形式相关的知识,希望对你有一定的参考价值。
书籍来源:《Go语言精进之路:从新手到高手的编程思想、方法和技巧》
一边学习一边整理读书笔记,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:《Go语言精进之路》读书笔记 | 汇总_COCOgsta的博客-CSDN博客
Go语言沿袭了静态编译型语言的传统:使用变量之前需要先进行变量的声明。
Go语言有两类变量。
包级变量(package variable):在package级别可见的变量。局部变量(local variable):函数或方法体内声明的变量,仅在函数或方法体内可见
8.1 包级变量的声明形式
包级变量只能使用带有var关键字的变量声明形式。从声明变量时是否延迟初始化对包级变量进行一次分类。
- 声明并同时显式初始化
在声明变量的同时进行显式初始化,实践中多使用下面的格式:
var variableName = InitExpression
复制代码
Go编译器会自动根据等号右侧的InitExpression表达式求值的类型确定左侧所声明变量的类型。
如果InitExpression采用的是不带有类型信息的常量表达式,比如下面的语句:
var a = 17
var f = 3.14
复制代码
则包级变量会被设置为常量表达式的默认类型:以整型值初始化的变量a,Go编译器会将之设置为默认类型int;而以浮点值初始化的变量f,Go编译器会将之设置为默认类型float64。
显式为包级变量a和f指定类型,那么有以下两种声明方式:
// 第一种
var a int32 = 17
var f float32 = 3.14
// 第二种
var a = int32(17)
var f = float32(3.14)
复制代码
Go语言官方更推荐后者。
- 声明但延迟初始化
对于声明时并不显式初始化的包级变量,使用最基本的声明形式:
var a int32
var f float64
复制代码
虽然没有显式初始化,但Go语言会让这些变量拥有初始的“零值”。
- 声明聚类与就近原则
Go语言提供var块用于将多个变量声明语句放在一起,一般将同一类的变量声明放在一个var块中,将不同类的声明放在不同的var块中;或者将延迟初始化的变量声明放在一个var块,而将声明并显式初始化的变量放在另一个var块中。笔者称之为“声明聚类”。比如:
// $GOROOT/src/net/http/server.go
var (
bufioReaderPool sync.Pool
bufioWriter2kPool sync.Pool
bufioWriter4kPool sync.Pool
)
var copyBufPool = sync.Pool
New: func() interface
b := make([]byte, 32*1024)
return &b
,
...
// $GOROOT/src/net/net.go
var (
aLongTimeAgo = time.Unix(1, 0)
noDeadline = time.Time
noCancel = (chan struct)(nil)
)
var threadLimit chan struct
...
复制代码
copyBufPool变量没有被放入var块中,因为它的声明带有显式初始化,而var块中的变量声明都是延迟初始化的;hreadLimit被单独放在var块外面,考虑它是延迟初始化的变量声明,与var块中标识时间限制的变量有所不同。
大家可能有一个问题:是否应当将包级变量的声明全部集中放在源文件头部呢?使用静态编程语言的开发人员都知道,变量声明最佳实践中还有一条:就近原则,即尽可能在靠近第一次使用变量的位置声明该变量。就近原则实际上是变量的作用域最小化的一种实现手段。在Go标准库中我们很容易找到符合就近原则的变量声明例子,比如下面这个:
// $GOROOT/src/net/http/request.go
var ErrNoCookie = errors.New("http: named cookie not present")
func (r *Request) Cookie(name string) (*Cookie, error)
for _, c := range readCookies(r.Header, name)
return c, nil
return nil, ErrNoCookie
复制代码
如果在源文件中,仅某个方法用到了包级变量,则可在临近该方法定义的位置声明该变量。如果一个包级变量在包内部被多处使用,那么这个变量还是放在源文件头部声明比较适合。
8.2 局部变量的声明形式
与包级变量相比,局部变量多了一种短变量声明形式,这也是局部变量采用最多的一种声明形式。
- 对于延迟初始化的局部变量声明,采用带有var关键字的声明形式
一种常见的采用带var关键字声明形式的变量是buf,另一种常见的采用带var关键字声明形式的变量是error类型的变量err。
- 对于声明且显式初始化的局部变量,建议使用短变量声明形式
短变量声明形式是局部变量最常用的声明形式:
a := 17
f := 3.14
s := "hello, gopher!"
复制代码
对于不接受默认类型的变量,依然可以使用短变量声明形式,只是在“:=”右侧要进行显式转型:
a := int32(17)
f := float32(3.14)
s := []byte("hello, gopher!")
复制代码
- 尽量在分支控制时应用短变量声明形式
很少单独声明在分支控制语句中使用的变量,而是通过短变量声明形式将其与if、for等融合在一起:
// $GOROOT/src/net/net.go
func (v *Buffers) WriteTo(w io.Writer) (n int64, err error)
// 笔者注:在if循环控制语句中使用短变量声明形式
if wv, ok := w.(buffersWriter); ok
return wv.writeBuffers(v)
// 笔者注:在for条件控制语句中使用短变量声明形式
for _, b := range *v
nb, err := w.Write(b)
n += int64(nb)
if err != nil
v.consume(n)
return n, err
v.consume(n)
return n, nil
复制代码
以上是关于《Go语言精进之路》读书笔记 | 使用一致的变量声明形式的主要内容,如果未能解决你的问题,请参考以下文章
《Go语言精进之路》读书笔记 | 了解string实现原理并高效使用
《Go语言精进之路》读书笔记 | 使用复合字面值作为初值构造器