0 变量声明
作为强类型系统的编程语言,Go语言使用的任何变量都需要像C语言那样显式的声明和定义,what’s more,Go语言不支持隐式类型转换,这从某种程度上来说提升了安全性。
Go语言声明变量的方式有很多种,并没有进行统一,但是也存在一些约定俗成的习惯,大致如下:
- 声明并显式初始化包级变量:
var a int = 10
- Go语言显示声明变量(variable)的关键字为var
- Go语言变量类型的位置放在变量名称后面
- 变量类型也可省略,令编译器自动推导,如
var a = 10
- 声明但延迟初始化包级变量:
// 此时可能尚未确定如何确定a的初始化值
var a int
// 一些操作之后a的初始化值可以确定
a = 10
- 使用自动推导的方式定义局部变量
a := 10
- Go语言支持以上的短变量声明方式,但只可用于局部变量
- 变量的类型会以字面量的值进行自动推导,该过程发生在编译阶段
1 整数
整数应该是所有编程语言中用到次数最多的数据类型,Go语言也不例外,和大多数语言一样,Go语言按照有无符号和长度将整数类型进行分类
长度 | 有符号 | 无符号 |
---|---|---|
8 | int8 | uint8 |
16 | int16 | uint16 |
32 | int32 | uint32 |
64 | int64 | uint64 |
int | uint |
- 未显式说明长度时(int和uint),其实际占用字节数去决定运行的计算机字长:一般为32或64
- 无符号类型uint表示的正数范围是int的2倍
- 由于Go语言不支持隐式类型转换,即使同样是整数(比如int8和int16)类型的变量,也不能直接进行相加
package main
import "fmt"
func main() {
var a int8 = 10
var b int16 = 20
var c int32 = 30
var d int64 = 40
var e int = 50
// 自动推导
f := 60
var g = 70
fmt.Println(a, b, c, d, e, f, g)
fmt.Printf("%T\n", a)
fmt.Printf("%T\n", b)
fmt.Printf("%T\n", c)
fmt.Printf("%T\n", d)
fmt.Printf("%T\n", e)
fmt.Printf("%T\n", f)
fmt.Printf("%T\n", g)
// 必须显式类型转换
c = int32(a) + int32(b)
fmt.Println(c)
}
该demo的运行结果如下,uint的结果是类似的:
2 浮点数
浮点数整体与C语言的分类准则一致,根据占用内存字节数划分为float32和float64,前者相当于C语言的float,后者相当于double,float64的精度由于占用内存更多的缘故要比float32大很多,结合使用时注意不要忘记转换类型就行(可能会有精度丢失)
package main
import "fmt"
func main() {
var a float32 = 3.14
var b float64 = 1.56
c := 7.38
fmt.Println(a, b, c)
fmt.Printf("%T\n", a)
fmt.Printf("%T\n", b)
fmt.Printf("%T\n", c)
c = float64(a) + b
fmt.Println(c)
}
该demo运行结果如下:
- 可以看到,将a由float32转换为float64类型后与b相加,结果并不是期望的4.70,而是4.700000104904175,这是由于float32和float64在内存中的表示方式不同导致的,因此,使用浮点数类型时一定要慎重!
3 布尔
C语言原生是不支持布尔类型的变量的,除非包含对应的头文件#include <stdbool.h>
,但总归还是不得劲,Go语言则在语言层面支持布尔类型,其只有两种可能的取值:true和false。在控制流语句(如条件判断和循环)中广泛使用
package main
import "fmt"
func main() {
var a bool
b := true
// 默认值为false
fmt.Println(a, b)
fmt.Println(a && b)
fmt.Println(a || b)
fmt.Println(!a)
}
该demo运行结果如下:
4 字符
4.1 byte
- 定义:byte 是 uint8 的别名,表示一个 8 位无符号整数。范围是 0 到 255。
- 用途:主要用于处理原始字节数据,例如文件读写、网络通信、字符串处理等
package main
import "fmt"
func main() {
var b byte = 65
fmt.Println(b)
fmt.Printf("%c\n", b)
// 使用 byte 数组表示字符串
str := []byte("Hello")
fmt.Println(str)
fmt.Printf("%s\n", str)
}
该demo运行结果如下:
4.2 rune
- 定义:rune 是 int32 的别名,表示一个 32 位有符号整数。范围是 -2^31 到 2^31 - 1。它用于表示 Unicode 代码点。
- 用途:主要用于处理 Unicode 字符,可以表示所有的 Unicode 字符。
package main
import "fmt"
func main() {
var r rune = '世'
fmt.Println(r)
fmt.Printf("%c\n", r)
// 使用 rune 数组表示字符串
str := []rune("你好")
fmt.Println(str)
fmt.Printf("%s\n", string(str))
}
该demo运行结果如下:
4.3 总结
- byte 是 uint8 的别名,主要用于处理原始字节数据。
- rune 是 int32 的别名,主要用于处理 Unicode 字符。
- 这两个类型在处理字符串和文本数据时非常有用,byte 适合处理字节序列,rune 适合处理 Unicode 代码点。
- 可以使用 for 循环按字节或按字符遍历字符串。
- byte 和 rune 之间可以进行类型转换,用于不同场景下的数据处理。