在编程语言中,为了方便操作内存特定位置的数据,我们用一个特定的名字与位于特定位置的内存块绑定在一起,这个名字被称为变量。
静态语言有别于动态语言的一个重要特征:变量声明,
比如PHP 动态 解释性语言,不必须设定变量的类型 就可以正常执行,由语言解释器自动计算 变量值得类型 ,常常发现 浮点类型的字段以及比较 会出现一些 问题
go语言静态编译型语言,设定声明变量的时候必须指定 变量的类型,不同变量类型 不能在一起计算
var a int = 1
var 声明变量关键词
a 变量名称
int 声明变量值类型
1 变量初始值
var a int //未置变量初始值,go语言会自动设置变量初始值 此时的 a 值为0
支持同时声明多个变量
方式1
var (
a int = 1
b string = "hell world"
c bool = false
)
方式2
var a, b, c int = 1, 2, 3
方式3
var (
a, b, c int = 1, 2,3
d, e, f rune = "A", "B", "C"
)
var a = 1
在常规的声明方式中 var a int = 1 隐藏了 int 变量类型关键词,go语言会通过 变量值 检测出当前变量的类型 是一个int
如果需要自己指定变量类型的值类型,可以自己用函数转化
var a = int16(1)
注意必须要设置变量值,下面这种设置方式不设置变量值会抛出异常
var a
同时声明多个变量
var a, b, c = 1, "123", true
a := 1
这种方式去掉了var 和 int,用:= 方式去声明变量 变量名 := 变量值,
同时声明多个变量
a, b, c := 1, true, 'H'
如果导出变量(大写字母开头),这种包级别变量也叫全局变量
包级变量只能使用带有 var 关键字的变量声明形式,不能使用短变量声明形式,但在形式细节上可以有一定灵活度
声明显示初始化分别区分
// $GOROOT/src/io/io.go
var ErrShortWrite = errors.New("short write")
var ErrShortBuffer = errors.New("short buffer")
var EOF = errors.New("EOF")
一般定义包级别变量 时使用省略 变量类型方式 var varName = varValue
如果要显示的展示包级别的变量类型
var a int = 1
//第一种:
var a = 13 // 使用默认类型
var b int32 = 17 // 显式指定类型
var f float32 = 3.14 // 显式指定类型
//相比较来说更推荐第二种:
var a = 13 // 使用默认类型
var b = int32(17) // 显式指定类型
var f = float32(3.14) // 显式指定类型
// 更推荐的方式1
var (
a = 13
b = int32(17)
c = float32(3.14)
)
// 更推荐的方式 2
var (
a = 13
b int32 = 17
c float32 =3.14
)
声明类聚
// $GOROOT/src/net/net.go
var (
netGo bool
netCgo bool
)
如上代码 把定义的相同类型的变量 放在一个块中聚合,代码更好阅读,使用也方便
就近原则
// $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
}
ErrNoCookie 包级别变量直接定义在 调用他的方法上面,更优于阅读代码,如果包级别变量在包中多个地方使用还是推荐放在 文件头部去声明变量
函数和方法中声明的变量,局部变量比包级别变量又多了一种短变量声明形式
//通用的变量声明方法
var a int
//不能使用省略和段变量声明,下面这两种会抛出语法错误
var b =
c :=
a := 17
f := 3.14
s := "hello, gopher!"
// $GOROOT/src/strings/strings.go
func LastIndexAny(s, chars string) int {
if chars == "" {
// Avoid scanning all of s.
return -1
}
if len(s) > 8 {
// 作者注:在if条件控制语句中使用短变量声明形式声明了if代码块中要使用的变量as和isASCII
if as, isASCII := makeASCIISet(chars); isASCII {
for i := len(s) - 1; i >= 0; i-- {
if as.contains(s[i]) {
return i
}
}
return -1
}
}
for i := len(s); i > 0; {
// 作者注:在for循环控制语句中使用短变量声明形式声明了for代码块中要使用的变量c
r, size := utf8.DecodeLastRuneInString(s[:i])
i -= size
for _, c := range chars {
if r == c {
return i
}
}
}
return -1
}
声明局部变量时遇到了适合聚类的应用场景,一定要 放在一个var 块中聚类出来
// $GOROOT/src/net/dial.go
func (r *Resolver) resolveAddrList(ctx context.Context, op, network,
addr string, hint Addr) (addrList, error) {
... ...
var (
tcp *TCPAddr
udp *UDPAddr
ip *IPAddr
wildcard bool
)
... ...
}
好记性不如烂笔头 本文学自 极客时间 Tony Bai · Go 语言第一课