变量,计算机语言能存储计算结果或表示值的抽象概念。可以通过变量名访问,变量名由字母、数字、下划线组成,其中首个字符不能为数字
var 声明语句可以创建一个特定类型的变量,然后给变量附加一个名字,并且设置变量的初始值。变量声明的一般语法如下:
var 变量名字 类型 = 表达式
**零值初始化机制可以确保每个声明的变量总是有一个良好定义的值,因此在 Go 语言中不存在未初始化的变量。**
var s string
fmt.Print(s) // ""
var i, j, k int // int, int, int, int
var b, f, s = true, 2.3, "four" // bool, float64, string
一组变量也可以通过调用一个函数,由函数返回的多个返回值初始化:
var f, err = os.Open(name) // os.Open returns a file and an erro
在函数内部,有一种称为简短变量声明语句的形式可用于声明和初始化局部变量。它以 “名字 := 表达式” 形式声明变量,变量的类型根据表达式来自动推导。
anim := gif.GIF{LoopCount: nframes}
freq := rand.Float64() * 3.0
t := 0.0
因为简洁和灵活的特点,**简短变量声明被广泛用于大部分的局部变量的声明和初始化。**var 形式的声明语句往往是用于需要显式指定变量类型地方,或者因为变量稍后会被重新赋值而初始值无关紧要的地方。
i := 100 // an int
var boiling float64 = 100 // a float64
var names []string
var err erro
var p Point
和 var 形式声明语句一样,简短变量声明语句也可以用来声明和初始化一组变量:
i, j := 0, 1
但是这种同时声明多个变量的方式应该限制只在可以提高代码可读性的地方使用,比如 for 语句的循环的初始化语句部分。
和普通 var 形式的变量声明语句一样,简短变量声明语句也可以用函数的返回值来声明和初始化变量。简短变量声明左边的变量可能并不是全部都是刚刚声明的。如果有一些已经在相同的词法域声明过了(§2.7),那么简短变量声明语句对这些已经声明过的变量就只有赋值行为了。
in, err := os.Open(infile)
// ...
out, err := os.Create(outfile)
简短变量声明语句中必须至少要声明一个新的变量,下面的代码将不能编译通过:
f, err := os.Open(infile)
// ...
f, err := os.Create(outfile) // compile error: no new variables
简短变量声明语句只有对已经在同级词法域声明过的变量才和赋值操作语句等价,如果变量是在外部词法域声明的,那么简短变量声明语句将会在当前词法域重新声明一个新的变量。
注:
常量是一个简单值的标识符,在程序运行时,不会被修改的量。数据类型只可以是**布尔型、数字型(整数型、浮点型和复数)和字符串型**。常量的定义格式:(省略类型说明符 type,因为编译器可以根据变量的值来推断其类型。)
// const identifier [type] = value
const b = "abc"
const c\_name1, c\_name2 = value1, value2
const pi = 3.14159 // approximately; math.Pi is a better approximation
常用于批量声明:
const (
e = 2.71828182845904523536028747135266249775724709369995957496696763
pi = 3.14159265358979323846264338327950288419716939937510582097494459
)
const (
Unknown = 0
Female = 1
Male = 2
)
0,1,2 代表未知、女、男
如果是批量声明的常量,除了第一个外其它的常量右边的初始化表达式都可以省略,如果省略初始化表达式则表示使用前面常量的初始化表达式写法,对应的常量类型也一样的。例如:
const (
a = 1
b
c = 2
d
)
fmt.Println(a, b, c, d) // "1 1 2 2"
所有常量的运算都可以在编译期完成,这样可以减少运行时的工作,也方便其他编译优化。当操作数是常量时,一些运行时的错误也可以在编译时被发现,例如整数除零、字符串索引越界、任何导致无效浮点数的操作等。
常量间的所有算术运算、逻辑运算和比较运算的结果也是常量,对常量的类型转换操作或以下函数调用都是返回常量结果:len、cap、real、imag、complex 和 unsafe.Sizeof。
因为它们的值是在编译期就确定的,因此常量可以是构成类型的一部分,例如用于指定数组类型的长度:
const IPv4Len = 4
// parseIPv4 parses an IPv4 address (d.d.d.d).
func parseIPv4(s string) IP {
var p [IPv4Len]byte
// ...
}
如果只是简单地复制右边的常量表达式,其实并没有太实用的价值。但是它可以带来其它的特性,那就是 iota 常量生成器语法。
枚举,将变量的值一一列举出来,变量只限于列举出来的值的范围内取值。Go 语言中没有枚举这种数据类型的,但是可以使用 const 配合 iota 模式来实现。
常量声明可以使用 iota 常量生成器初始化,它用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。在一个 const 声明语句中,在第一个声明的常量所在的行,iota 将会被置为 0,然后在每一个有常量声明的行加一。
\*\*1. 普通枚举\*\*
const (
a = 0
b = 1
c = 2
d = 3
)
\*\*2. 自增枚举\*\*
const (
a = iota //0
c //1
d //2
)
const (
e, f = iota, iota //e=0, f=0
g = iota //g=1
)
type Weekday int
const (
Sunday Weekday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
\*\*3. 显式恢复\*\*
const (
a = iota //0
b //1
c = 100 //100
d //100
e = iota //4
)
\*\*4. 求幂次\*\*
type Flags uint
const (
FlagUp Flags = 1 << iota // is up
FlagBroadcast // supports broadcast access capability
FlagLoopback // is a loopback interface
FlagPointToPoint // belongs to a point-to-point link
FlagMulticast // supports multicast access capability
)
注:<< 表示左移的意思,即<<n==*(2^n)。
本例表示随着 iota 的递增,每个常量对应表达式 1 << iota,是连续的 2 的幂。
更复杂的例子,每个常量都是1024的幂:
const (
\_ = 1 << (10 \* iota)
KiB // 1024
MiB // 1048576
GiB // 1073741824
TiB // 1099511627776 (exceeds 1 << 32)
PiB // 1125899906842624
EiB // 1152921504606846976
ZiB // 1180591620717411303424 (exceeds 1 << 64)
YiB // 1208925819614629174706176
)
_ 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。
不过 iota 常量生成规则也有其局限性。例如,它并不能用于产生 1000 的幂(KB、MB 等),因为 Go 语言并没有计算幂的运算符。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。