这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。
Go 语言的变量可以分为两类
包级变量 (package varible)
- 也就是在包级别可见的变量
- 如果是导出变量(大写字母开头),那么这个包级变量也可以被视为全局变量(被其他包引用)
- 所有的函数都可以使用,而且共享这一份数据
局部变量 (local varible)
- 也就是 Go 函数或方法体内声明的变量,仅在函数或方法体内可见
- 变量在哪里定义,就只能在哪个范围使用,超出这个范围,我们认为变量就被销毁了
实际 🌰
package main
import "fmt"
// 包级变量
var all_sum int
func add(x int, y int) int {
// 局部变量 sum
sum := x + y
// 函数体内可访问包级变量
all_sum += sum
return sum
}
func main() {
fmt.Println(
add(1, 2),
add(3, 4),
all_sum,
)
}
运行结果
3 7 10
包级变量的声明方式
包级变量只能使用带有 var 关键字的变量声明形式,不能使用短变量声明形式
可以显式地为包级变量指定类型
// 第一种
var a = 13 // 使用默认类型
var b int32 = 18 // 显式指定类型
var f float32 = 3.14 // 显式指定类型
// 第二种
var a1 = 13 // 使用默认类型
var b1 = int32(32) // 显式指定类型
var f1 = float32(3.14) // 显式指定类型
Go 推荐使用第二种写法,以及下面的形式
var (
a2 = 13
b2 = int32(17)
f2 = float32(3.14)
)
声明但延迟初始化
声明包级变量但不立即显式初始化的包级变量
var a int32
var f float32
- Go 也会让这些变量拥有初始的零值
- 如果是自定义的类型,建议尽量保证它的零值是可用的
声明聚类
建议将同一类的变量声明放在一个 var 变量声明块中,不同类的声明放在不同的var 声明块中
// 将延迟初始化的变量声明放在这个块中
var (
netGo bool
netCgo bool
)
// 将显式初始化的变量放在这个块中
var (
aLongTimeAgo = time.Unix(1, 0)
noDeadline = time.Time{}
noCancel = (chan struct{})(nil)
)
这种就是声明聚类,提高代码可读性
就近原则
ErrNoCookie 这个变量在整个包中仅仅被用在了 Cookie 方法中,因此它被声明在紧邻 Cookie 方法定义的地方更合理
// $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
}
如果一个包级变量在包内部被多处使用,那么这个变量还是放在源文件头部声明比较适合的
局部变量的声明方式
// 第一种:延迟初始化的变量声明
var (
a int
b bool
)
// 第二种:显式声明类型或初始化赋值
var (
var c = 13
var d = float64(3.14)
)
// 第三种:短变量声明方式
e := 13
f := 3.14
尽量在分支控制时使用短变量声明形式
这是 strings 包的 LastIndexAny 函数
func LastIndexAny(s, chars string) int {
...
if len(s) > 8 {
// 短变量声明了 as、isASCII,他们可以在 if 代码块中使用
if as, isASCII := makeASCIISet(chars); isASCII {
for i := len(s) - 1; i >= 0; i-- {
if as.contains(s[i]) {
return i
}
}
return -1
}
}
...
// 短变量声明了 i,他可以在 for 代码块中使用
for i := len(s); i > 0; {
r, size := utf8.DecodeLastRuneInString(s[:i])
i -= size
if IndexRune(chars, r) >= 0 {
return i
}
}
return -1
}