Golang学习笔记-02变量常量

变量

什么是变量

变量是为存储特定类型的值而提供给内存位置的名称。在go中声明变量有多种语法。

所以变量的本质就是一小块内存,用于存储数据,在程序运行过程中数值可以改变。

变量的声明

单变量声明

Go语言的变量声明格式为:

1
var 变量名 变量类型

第一种,指定变量类型,声明后若不赋值,使用默认值

以关键字var开头,变量类型放在变量的后面,行尾无需分号。例如

1
2
3
var name string
var age int
var isOk bool

第二种,根据值自行判定变量类型(类型推断Type inference)

如果一个变量有一个初始值,编译器会根据等号右边的值来推导变量的类型完成初始化。因此,如果变量具有初始值,则可以省略变量声明中的类型。

注意,虽然go可以省略变量类型来声明变量,但实际上go还是一个强类型的语言.

1
var name = value

第三种,省略var,(简短声明)

:=左侧的变量不应该是已经声明过的(多个变量同时声明时,至少保证一个是新变量),否则会导致编译错误

注意,这种方式它只能被用在函数体内,而不可以用于全局变量的声明与赋值

1
2
3
4
5
6
name := value

// 例如
var a int = 10
var b = 10
c : = 10
多变量声明

每声明一个变量就需要写var关键字会比较繁琐,go语言中还支持批量变量声明:

第一种,以逗号分隔,声明与赋值分开,若不赋值,存在默认值

前面的几个变量的type都相同时,可以直接在最后一个变量后面写一个type类型,表示这几个变量的类型都是这个type

1
2
var name1, name2, name3 type
name1, name2, name3 = v1, v2, v3

第二种,直接赋值,下面的变量类型可以是不同的类型

1
var name1, name2, name3 = v1, v2, v3

第三种,集合类型

1
2
3
4
var (
name1 type1
name2 type2
)

例如:

1
2
3
4
5
6
var (
a string
b int
c bool
d float32
)

匿名变量

在使用多重赋值时,如果想要忽略某个值,可以使用匿名变量(anonymous variable)。 匿名变量用一个下划线_表示,例如:

1
2
3
4
5
6
7
8
9
func foo() (int, string) {
return 10, "Q1mi"
}
func main() {
x, _ := foo()
_, y := foo()
fmt.Println("x=", x)
fmt.Println("y=", y)
}

匿名变量不占用命名空间,不会分配内存,所以匿名变量之间不存在重复声明。 在某些编程语言里,匿名变量也被叫做哑元变量。

注意事项

  • 变量必须先定义才能使用
  • go语言是强类型静态语言,要求变量的类型和赋值的类型必须一致。
  • 变量名不能冲突。(同一个作用于域内不能冲突)
  • 简短定义方式,左边的变量名至少有一个是新的
  • 简短定义方式:=不能使用在函数外,即不能定义全局变量。
  • 变量的零值。也叫默认值。
  • 变量定义了就要使用,否则无法通过编译。
  • 函数外的每个语句都必须以关键字开始(var、const、func等)
  • _多用于占位,表示忽略值。

已经被初始化声明的变量不可再次被初始化声明,只能对该变量进行赋值操作。否则编译器报错。

如果你在定义变量 a 之前使用它,则会得到编译错误 undefined: a。如果你声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误,此外,单纯地给 a 赋值也是不够的,这个值必须被使用。

在同一个作用域中,已存在同名的变量,则之后的声明初始化,则退化为赋值操作。但这个前提是,最少要有一个新的变量被定义,且在同一作用域,例如,下面的y就是新定义的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import (
"fmt"
)

func main() {
x := 140
fmt.Println(&x)
x, y := 200, "abc"
fmt.Println(&x, x)
fmt.Print(y)
}

运行结果:

1
2
3
0xc04200a2b0
0xc04200a2b0 200
abc

常量

相对于变量,常量是恒定不变的值,多用于定义程序运行期间不会改变的那些值。

常量的声明

常量的声明和变量声明非常类似,只是把var换成了const

常量在定义的时候必须赋值,且在运行过程中不能也不可能被改变,如果常量初始化赋值后尝试对其再次赋值,编译器会报错不通过。

1
const identifier [type] = value

当然,常量也是可以类型推导的

1
2
const b string = "abc" //显式类型定义
const b = "abc" //类型推导,隐式类型定义

例:

1
2
const pi = 3.1415
const e = 2.7182

声明了pie这两个常量之后,在整个程序运行期间它们的值都不能再发生变化了。

多个常量也可以一起声明,组成常量组

1
2
3
4
const (
pi = 3.1415
e = 2.7182
)

const同时声明多个常量时,如不指定类型和初始化值,则与上一行非空常量右值相同

1
2
3
4
5
6
const (
x uint16 = 16
y
s = "abc"
z
)

运行结果:

1
2
uint16,16
string,abc

常量的注意事项:

  • 常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型

  • 不曾使用的常量,在编译的时候,是不会报错的(变量声明了就必须使用)

iota

iota,特殊常量,可以认为是一个可以被编译器修改的常量.

iota是go语言的常量计数器,只能在常量的表达式中使用。
iota在const关键字出现时将被重置为0。
const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。
使用iota能简化定义,在定义枚举时很有用。

iota 可以被用作枚举值:

1
2
3
4
5
6
const (
n1 = iota //0
n2 //1
n3 //2
n4 //3
)

等同于,虽然每项都等于iota,但是iota的值在上一个常量被初始化声明后变化了,导致该常量的值与上一个不同

1
2
3
4
5
6
const (
n1 = iota //0
n2 = iota //1
n3 = iota //2
n4 = iota //3
)

第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;所以 a=0, b=1, c=2 可以简写为如下形式:

1
2
3
4
5
const (
a = iota
b
c
)

iota 用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

func main() {
const (
a = iota //0
b //1
c //2
d = "ha" //独立值,iota += 1
e //"ha" iota += 1
f = 100 //iota +=1
g //100 iota +=1
h = iota //7,恢复计数
i //8
)
fmt.Println(a,b,c,d,e,f,g,h,i)
}

运行结果:

1
0 1 2 ha ha 100 100 7 8

其他示例:

使用_跳过某些值

1
2
3
4
5
6
const (
n1 = iota //0
n2 //1
_
n4 //3
)

iota声明中间插队

1
2
3
4
5
6
7
const (
n1 = iota //0
n2 = 100 //100
n3 = iota //2
n4 //3
)
const n5 = iota //0

定义数量级 (这里的<<表示左移操作,1<<10表示将1的二进制表示向左移10位,也就是由1变成了10000000000,也就是十进制的1024。同理2<<2表示将2的二进制表示向左移2位,也就是由10变成了1000,也就是十进制的8。)

1
2
3
4
5
6
7
8
const (
_ = iota
KB = 1 << (10 * iota)
MB = 1 << (10 * iota)
GB = 1 << (10 * iota)
TB = 1 << (10 * iota)
PB = 1 << (10 * iota)
)

多个iota定义在一行

1
2
3
4
5
const (
a, b = iota + 1, iota + 2 //1,2
c, d //2,3
e, f //3,4
)

如果中断iota自增,则必须显式恢复。且后续自增值按行序递增

自增默认是int类型,可以自行进行显示指定类型

数字常量不会分配存储空间,无须像变量那样通过内存寻址来取值,因此无法获取地址【数字常量是获取某一固定内存块】

零值

Go任何类型在未初始化时都对应一个零值:布尔类型是false,整型是0,字符串是””,而指针,函数,interface,slice,channel和map的零值都是nil。

文章作者: Oxywen
文章链接: https://oxywen.cn/post/go/3/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 不闻星河须臾