Go语言--变量、常量

tech2024-05-29  76

一、变量

1.1 声明变量

1、标准格式 var 变量名 变量类型 Q:为什么Go语言把数据类型放在后面? 答:Go语言这是一种自左向右的声明风格,这种声明的风格的好处是,变量名和类型是完全分隔的。当类型变得复杂时,它的价值就体现出来了。 特别类型是函数指针的时候,C语言的声明语法容易让人弄混淆,而Go语言的这种自左向右的声明语法,即使在冗长的声明中也能很清晰地知道整个声明结构。 x int //声明变量 p *int //声明指针 a [3]int //声明数组 func f(a int, b int) int //声明函数,函数名为f

 <说明> Go语言的变量声明是以var关键字开头,后置变量类型,行尾无须分号。

2、批量格式

var ( a int b string c []float32 d func() bool e struct { x int } )

 批量格式使用var和小括号(),可以将一组变量定义在一起。

指针

    在Go语言中,数组(array)和切片(slice)在声明时,类型语法把方括号放在了类型的左边,但是在表达式语法中却又把方括号放在了右边。 var a []int //声明int型切片 x = a[1] //将切片元素赋值给变量x //类似的,Go语言的指针沿用了C的星号(*)的记法,声明的时候星号是在变量名的右边,但在表达式语法中却又把星号放在变量的左边: var p *int //声明int型指针p x = *p //将指针p所指向的内存单元的值赋值给变量x

可以看到,Go语言的指针的声明与C语言是不一样的,但是对指针的运算使用的语法是相同的。

1.2 初始化变量

Go语言在声明变量时,会自动对变量对应的内存区域进行初始化操作。每个变量都被初始化其类型的默认值。例如:

整型和浮点型变量的默认值是0。字符串变量的默认值为空字符串。布尔型变量的默认值是false。切片、函数、指针变量、接口变量的默认值是nil。 当然,你也可以在声明变量的同时赋予变量一个初始值。 <回顾> 在C/C++语言中,在声明变量时,并不会对变量对应内存区域进行清理操作。此时,变量值可能是完全不可预期的结果。开发者需要习惯在声明变量的同时进行初始化操作,稍有不慎,就会造成不可预知的后果。   1、标准格式 var 变量名 类型 = 表达式 示例如下: var hp int = 100

2、编译器推导类型的格式

在上面标准的基础上,将类型int省略,编译器会根据等号右边的表达式推导出等号右边的hp变量的类型。因此,上面的语句简写成下面的语句:

var hp = 100

等号右边的部分在编译原理中被称作“右值”。

下面的一个例子:

var attack 40 var defence 20 var damageRate float32 = 0.17 var damage = float32(attack-defence) * damageRate

Go语言和C语言一样,编译器会尽量提供精确度,以避免计算中精度损失。默认情况下,如果不指定damageRate变量的类型,Go语言编译器会将damageRate类型推导为float64。本例中,指定了其类型为float32,所以不需要float64的精度。

float(attack-defence)将两个整型变量相减后的结果强制转换为float32类型,然后再与float32类型的damageRate相乘,因此damage类型也是float32类型。

<建议> 在实际的开发过程中,不太建议使用这种简写的变量初始化方式,最好还是带上类型,即使用标准格式来初始化变量。

3、短变量声明并初始化

var的变量声明还有一种更为精简的写法,例如:

hp := 100

这是Go语言的推导声明写法,编译器会自动根据右值类型推断出左值的对应类型。

<注意> 由于使用了":=",而不是赋值符号"=",因此推导声明的左值变量必须是一个没有定义过的变量。若已经定义过,将会发生编译报错。例如:

var hp int hp := 100

编译时会报错:no new variables on left side of :=

提示,在:=左边没有新变量出现,意思就是“:=” 的左边变量已经被声明过了。短变量的声明方式在开发中的例子较多,例如:

conn, err := net.Dial("tcp", "127.0.0.1:8080")

 如果是标准声明格式,将会变成:

var conn net.Conn var err error conn, err := net.Dial("tcp", "127.0.0.1:8080")

因此,短遍历声明并初始化的格式在开发中使用比较普遍。因为它可以简化代码的书写。

《注意》在多个短变量声明和赋值时,至少要有一个新声明的变量出现在左值中,即便其他变量名是重复声明的,编译器也不会报错。

例如:

conn, err := net.Dial("tcp", "127.0.0.1:8080") conn2, err := net.Dial("tcp", "127.0.0.1:8080")

上面的代码片段中,编译器不会报err重复定义的错误。

1.3 多个变量同时赋值(多重赋值)

使用Go语言的“多重赋值”特性,可以轻松完成两个变量的交换。

var a int = 100 var b int = 200 b, a = a, b 多重赋值时,变量的左值和右值按从左到右的顺序赋值。即先是=号右边的a先赋值给左边的b,然后是=号右边的b赋值给=号左边的a。多重赋值在Go语言的错误处理和函数返回值中会大量地使用。

例如,使用Go语言进行排序时就需要使用多重交换。

type IntSlice []int //将[]int声明为IntSlice类型 func (p IntSlice) Len() int { return len(p) } //切片长度函数 func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] } //根据索引比较元素的大小并返回结果 func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } //根据索引交换两个元素的值

1.4 匿名变量

在使用多重赋值时,如果不需要在左值中接收变量值,可以使用匿名变量。Go语言中匿名遍历是一个下划线"_"。使用匿名变量时,只需要在变量声明的地方使用下划线替换即可。

例如:

func GetData() (int, int) { return 100, 200 } a, _ := GetData() _, b := GetData()

匿名变量的特点:匿名变量不占用内存空间,不会进行内存分配。匿名变量与匿名变量之间也不会因为多次声明而无法使用。可以将匿名变量理解为一种占位符。

二、常量

常量是恒定不变的量,例如圆周率。可以在编译器对常量表达式进行计算求值,并在运行期使用该计算结果,但是计算结果无法被修改。

常量的声明使用关键字const。例如:

const PI = 3.1415926 const e = 2.718281

多个常量也可一起声明,使用const关键字+小括号。例如:

const ( PI = 3.1415926 e = 2.718281 )

因为常量的值是在编译器确定,所以可以用于数组声明。例如:

const sise = 4 var arr [size]int

2.1 枚举常量 —— 一组常量值

 Go语言目前还没有枚举类型(目前最新版是Go1.15),但是可以使用常量配合itoa模拟枚举常量。示例:

type Weapon int const ( Arrow Weapon = itoa //开始生成枚举值,默认值为0 Shuriken SniperRifle Rifle Blower ) //输出所有枚举值 fmt.Println(Arrow, Shuriken, SniperRifle, Rifle, Blower) //使用枚举类型并赋值 var weapon Weapon = Blower fmt.Println(weapon)

代码输出结果如下:

0 1 2 3 4

4

《代码说明》

将int类型定义为Weapon类型,这只是为int类型设置了一个类型别名(Type Alias)。就像枚举类型其实本质是整型一样。当然,某些情况下,如果需要int32和int64的枚举,也是可以的。将Arrow常量的类型标识为Weapon类型后,const下方的常量可以是默认类型的,默认时,默认使用前面指定的类型作为常量类型。因此Arrow后面的常量默认也都是Weapon类型了。使用itoa可以进行常量值的自动生成。itoa的起始值是0,一般情况下也是建议枚举值从0开始。一个const声明内的每一行常量声明,将会自动套用前面的itoa格式,并自动增加,默认增加1。当然,itoa不仅仅只生成每次增加1的枚举常量。还可以利用itoa来做一些强大的枚举常量值生成器。例如,下面的代码可以方便生成标志位常量: const ( FlagNone = 1 << itoa FlagRed FlagGreen FlagBlue ) fmt.Printf("%d %d %d\n", FlagRed, FlagGreen, FlagBlue) fmt.Printf("%b %b %b", FlagRed, FlagGreen, FlagBlue) //以二进制格式输出 输出结果: 2 4 8 10 100 1000 《代码说明》本例子中,itoa使用了移位操作,每次将上一次的值左移一位,以做出每一位的常量值。以二进制格式输出,可以清晰地看到每一位的变化。   示例程序:将枚举值转换为字符串。 /* 程序描述:将枚举值转换成字符串。 说明: Go语言没有枚举类型,可以使用常量配合iota模拟枚举。 */ package main import "fmt" //将ChipType定义为int类型 type ChipType int const ( None ChipType = iota //iota从0开始计数 CPU GPU ) //定义ChipType类型的方法String(),返回字符串 func (c ChipType) String() string { switch c { case None: return "None" case CPU: return "CPU" case GPU: return "GPU" } return "N/A" } func main() { //输出CPU的值并以整数格式显示 fmt.Printf("%s %d\n", CPU, CPU) }

输出结果:CPU 1

《代码说明》这里我们实现了ChipType类型的String()方法,当这个类型需要显示为字符串时,Go语言会自动寻找String()方法并进行调用。输出格式%s对应的是字符串类型,%d对应的是整型。

 

最新回复(0)