Day02(入门基础)
数据类型
整型
有符号整型(Signed Integer)和无符号整型(Unsigned Integer)是计算机编程中两种基本的整型数据类型,它们的主要区别在于如何解释存储在计算机中的二进制数值
-
有符号整型(Signed Integer)
- 表示范围:有符号整型可以表示正数、负数和零。因为它们需要表示正负,所以它们的取值范围是关于零对称的。例如,一个 8 位的有符号整型(
int8
),可以表示-128 到 127 之间的整数。 - 表示方法:在计算机内部,有符号整型的最高位(也称为符号位)用于表示数的正负。通常,如果符号位为 0,表示该数为正;如果符号位为 1,表示该数为负。剩下的位用于表示数值的大小。有符号整数的表示方法通常有两种:原码、反码和补码,其中补码是最常用的表示方法。
- 应用场景:当需要处理的数据可能为正数、负数或零时,应使用有符号整型。
- 表示范围:有符号整型可以表示正数、负数和零。因为它们需要表示正负,所以它们的取值范围是关于零对称的。例如,一个 8 位的有符号整型(
-
无符号整型(Unsigned Integer)
- 表示范围:无符号整型只能表示正数和零,不能表示负数。因此,它们的取值范围是从 0 到某个最大值。例如,一个 8 位的无符号整型(
uint8
),可以表示 0 到 255 之间的整数。 - 表示方法:无符号整型的所有位都用于表示数值的大小,没有专门的符号位。因此,对于相同位数的整型,无符号整型能够表示的数值范围是有符号整型的两倍(仅考虑正数部分)。
-
应用场景:当处理的数据只可能为正数或零时,如表示像素值、颜色分量、数量、大小等,应使用无符号整型。此外,在网络通信和硬件编程中,无符号整型也经常被用来表示数据的大小、地址偏移等。
类型名称 位大小 最小值 最大值 int8
8 位 -128 127 int16
16 位 -32,768 32,767 int32
(或rune
)32 位 -2,147,483,648 2,147,483,647 int64
64 位 -9,223,372,036,854,775,808 9,223,372,036,854,775,807 uint8
(或byte
)8 位 0 255 uint16
16 位 0 65,535 uint32
32 位 0 4,294,967,295 uint64
64 位 0 18,446,744,073,709,551,615
- 表示范围:无符号整型只能表示正数和零,不能表示负数。因此,它们的取值范围是从 0 到某个最大值。例如,一个 8 位的无符号整型(
浮点型
浮点型分为
float32
和float64
两种,分别表示 32 位和 64 位的浮点数值。以下是这两种浮点型的范围,以表格形式呈现:
类型名称 | 位大小 | 最小值 | 最大值 |
---|---|---|---|
float32 |
32 位 | 约等于 -3.4028235e+38 |
约等于 3.4028235e+38 |
float64 |
64 位 | 约等于 -1.7976931348623157e+308 |
约等于 1.7976931348623157e+308 |
通常推荐使用
float64
类型,因为它提供了更高的精度和更大的取值范围。然而,在需要节省内存空间或对性能有严格要求的场景下,可以考虑使用float32
类型
布尔型
布尔型使用
bool
类型表示,布尔型只有两个取值
- true
- false(默认)
字符串类型
在 Go 语言中,字符串类型(string)是一种内置的数据类型,用于表示文本数据。字符串是由零个或多个字符组成的序列,这些字符可以是字母、数字、标点符号、特殊字符等。
-
字符串在 Go 语言中的表示方式是用双引号(
""
)或反引号(``)括起来的一系列字符。例如1 2
s1 := "Hello, World!" s2 := `This is a raw string literal.`
-
在 Go 语言中,字符串是不可变的(immutable),即一旦创建了一个字符串,就不能再修改它的内容。如果需要修改字符串,通常需要创建一个新的字符串。
-
字符串在 Go 语言中的功能特点包括:
- 数据存储与序列化:字符串类型常用于数据的存储和序列化。例如,可以将数据转换为 JSON 格式的字符串进行存储和传输,或者将字符串解析为数据结构进行反序列化。
- 网络通信与数据交互:在网络通信和数据交互中,字符串类型用于表示和传输各种信息。例如,HTTP 请求和响应中的数据通常以字符串的形式进行传输,API 接口也常使用字符串表示参数和返回值。
- 文件读写与日志记录:字符串类型用于文件读写和日志记录,例如读取文本文件的内容、写入日志信息等。在文件读写和日志记录过程中,字符串类型能够有效地处理和操作文本数据。
-
字符串在 Go 语言中的内部表示通常是一个字符数组(byte slice)的引用,其中每个字符可能是一个字节(对于 ASCII 字符)或多个字节(对于 UTF-8 编码的多字节字符)。在 Go 语言中,字符串类型提供了许多内置的方法来操作和处理字符串,例如连接、拆分、查找、替换等。
-
此外,Go 语言还提供了两种特殊的字符类型来处理字符串中的字符:
byte
类型(等价于uint8
):用于表示 ASCII 字符集中的字符,每个字符占用一个字节。rune
类型(等价于int32
):用于表示 Unicode 字符集中的字符,可以表示包括中文、日文等任何 Unicode 字符。在处理包含多字节字符的字符串时,通常使用rune
类型来遍历和访问字符串中的每个字符。
其他
在 Go 语言中,除了整型(integer types)、浮点型(floating-point types)、布尔型(bool)和字符串类型(string)之外,还有其他几种基本数据类型。以下是 Go 语言中的一些主要数据类型:
复合类型
- 数组(Array):一种具有固定长度的序列,其中每个元素都是相同的数据类型。
- 切片(Slice):一种动态大小的、灵活的、可变的序列,底层是数组的引用。
- 映射(Map):一种无序的键值对集合,其中键是唯一的,并且可以是任何可比较的类型(如整数、字符串等)。
- 通道(Channel):一种类型安全的、阻塞的、先进先出的数据结构,用于在 Go 语言的 goroutine 之间进行通信。
接口类型
- 接口(Interface):一种抽象的类型,它定义了一组方法的集合。任何实现了这些方法的类型都满足这个接口。
函数类型
- 函数(Function):在 Go 语言中,函数也是一种类型,可以被赋值给变量或作为参数传递给其他函数。
指针类型
- 指针(Pointer):一个变量的地址。在 Go 语言中,可以使用指针来直接访问和操作内存中的数据。
其他基本类型
- 字节切片(Byte Slice):通常用于处理字节数据,如读取文件或网络数据时。虽然字节切片不是一种独立的数据类型,但它在 Go 编程中非常常见。
- rune:
rune
是int32
的别名,用于表示一个 Unicode 码点。它通常用于处理包含多字节字符的文本数据。 - 复数类型(Complex Types):Go 语言支持两种复数类型:
complex64
和complex128
,分别对应float32
和float64
的实部和虚部。
示例
以下是一些基本数据类型的示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var i int // 整型
var f float64 // 浮点型
var b bool // 布尔型
var s string // 字符串类型
var arr [5]int // 数组类型
var slc []int // 切片类型
var m map[string]int // 映射类型
var ch chan int // 通道类型
func myFunc() {} // 函数类型
var ptr *int // 指针类型
var c complex128 // 复数类型
var runeVar rune // rune 类型,用于表示Unicode码点
变量
基本介绍
在 Go 语言(通常被称为 Golang)中,变量是用于存储数据的标识符。变量有一个名称(也称为标识符),一个类型和一个值。下面是一些关于 Golang 变量的基本介绍:
变量声明
在 Golang 中,变量在使用之前必须先声明。可以使用关键字
var
来声明变量,或者可以使用短变量声明操作符:=
(这会自动推断变量的类型)。
-
使用
var
声明1 2 3
var name string var age int var isStudent bool
-
使用短变量声明操作符
:=
(也称为类型推导)1 2 3
name := "Alice" age := 30 isStudent := true
注意:使用
:=
声明的变量是自动初始化的,并且只能在函数内部使用(即它们是函数作用域的局部变量)。
变量类型
Golang 是一种静态类型语言,这意味着变量的类型在声明后不能更改。Golang 中的基本类型包括整数(如
int
,int8
,int16
,int32
,int64
,uint
,uint8
,uint16
,uint32
,uint64
,byte
等)、浮点数(如float32
,float64
)、复数(如complex64
,complex128
)、布尔值(bool
)、字符串(string
)等。此外,还有数组、切片、映射、通道和结构体等复合类型。
-
变量初始化
在声明变量时,可以使用赋值操作符
=
来初始化变量。如果声明了变量但没有初始化,那么它的值将是该类型的零值(例如,对于整数类型为 0,对于布尔类型为 false,对于字符串类型为空字符串”“等)。 -
变量作用域和生命周期:
- 作用域:变量可以在其声明的代码块(例如函数或循环)中访问。在函数内部声明的变量是局部变量,它们在该函数执行完毕后将不再存在。在函数外部声明的变量是全局变量,可以在整个包(package)中访问。
- 生命周期:变量的生命周期从它声明时开始,到其所在的代码块执行完毕时结束(对于局部变量)或程序结束时结束(对于全局变量)。在垃圾收集器运行期间,不再使用的变量所占用的内存将被自动释放。
-
命名规范: 变量名应遵循一定的命名规范以提高代码的可读性和可维护性。通常,变量名应该使用驼峰命名法(camelCase),并且应该具有描述性以反映其用途。避免使用与 Golang 关键字或内置函数名相同的变量名。
完整例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package main
import "fmt"
func main() {
// 使用 var 关键字声明变量
var name string
var age int
var isStudent bool
// 初始化变量
name = "Alice"
age = 30
isStudent = false
// 使用 fmt 包打印变量值
fmt.Println("Name:", name)
fmt.Println("Age:", age)
fmt.Println("Is Student:", isStudent)
// 使用短变量声明操作符 :=
grade := 90.5
fmt.Println("Grade:", grade)
// 声明并初始化一个字符串切片
fruits := []string{"apple", "banana", "cherry"}
fmt.Println("Fruits:", fruits)
// 遍历切片
for _, fruit := range fruits {
fmt.Println(fruit)
}
// 声明并初始化一个映射(map)
person := map[string]int{
"Alice": 25,
"Bob": 30,
"Charlie": 35,
}
// 访问映射中的值
fmt.Println("Bob's age from map:", person["Bob"])
// 如果键不存在,返回该类型的零值
fmt.Println("David's age from map (if exists):", person["David"])
}
在上面的示例中,我们展示了如何:
- 使用
var
关键字声明变量,并后续初始化它们。 - 使用短变量声明操作符
:=
来声明并初始化变量(在这种情况下,Go 语言会自动推断变量的类型)。 - 声明和初始化一个字符串切片(slice)并遍历它。
- 声明和初始化一个映射(map),并访问其中的值。
注意,当我们尝试访问映射中不存在的键时(如 “David”),Go 语言会返回该类型的零值(在这种情况下是 int
类型的零值,即 0
)。
iota
iota
是一个预定义的标识符,用于创建自增的无类型整数常量。它通常用于枚举类型,为每个枚举值生成一个唯一的常量。iota
的行为类似于一个计数器,每次在常量声明中出现时都会自增一次。
基本用法
iota
在每个const
关键字出现时被重置为 0,并在每个const
块中为每个新声明的常量自增。如果在同一行声明了多个常量,则它们将共享相同的iota
值,除非显式地给其中一个常量赋值。
使用示例
以下是一个使用iota
来定义星期几的枚举类型的示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main
import "fmt"
func main() {
const (
Sunday = iota // iota 初始化为 0
Monday // iota 自增为 1
Tuesday // iota 自增为 2
Wednesday // iota 自增为 3
Thursday // iota 自增为 4
Friday // iota 自增为 5
Saturday // iota 自增为 6
)
fmt.Println(Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) // 输出: 0 1 2 3 4 5 6
}
在这个例子中,iota
从 0 开始,并在每个新的常量声明中自动递增。因此,Sunday
的值为 0,Monday
的值为 1,依此类推。
递增规则
iota
从 0 开始递增。- 每个
const
块中的iota
值都会自动递增,不需要显式操作。 - 在同一个
const
块中,每次遇到iota
都会自增。 - 在不同的
const
块中,iota
会重新从 0 开始递增。
通过使用iota
,可以简洁地定义一系列有序的常量,提高代码的可读性和可维护性。
特殊例子
展示
iota
的特殊情况,包括在同一行声明多个常量时如何共享相同的iota
值,以及如何显式地给某个常量赋值以改变iota
的自动递增。
特殊情况示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main
import "fmt"
func main() {
const (
// iota 在这里初始化为 0
Sunday = iota // iota 值为 0
Monday // iota 值为 1
Tuesday // iota 值为 2
// 显式赋值会改变 iota 的值
WeekdayStart = Monday // WeekdayStart 值为 1,但 iota 仍然为 2
// 同一行声明的常量共享相同的 iota 值
Wednesday, Thursday = iota + 2, iota + 3 // Wednesday 值为 4,Thursday 值为 5
// iota 继续自增
Friday // iota 值为 6
Saturday // iota 值为 7
// 可以在新的 const 块中重置 iota
const (
firstQuarter = iota // iota 被重置为 0
secondQuarter // iota 值为 1
)
)
fmt.Println(Sunday, Monday, Tuesday, WeekdayStart) // 输出: 0 1 2 1
fmt.Println(Wednesday, Thursday, Friday, Saturday) // 输出: 4 5 6 7
fmt.Println(firstQuarter, secondQuarter) // 输出: 0 1
}
在这个例子中,首先定义了星期几的常量,并使用iota
进行自动递增。然后,我们显式地将Monday
的值赋给了WeekdayStart
,但请注意,这并不会改变iota
的自动递增行为,iota
的值在赋值之后继续递增。
接下来,在同一行声明了Wednesday
和Thursday
,并为它们分别赋了iota + 2
和iota + 3
的值。由于它们在同一行声明,所以它们都使用了同一个iota
值(此时为 2),但加上了不同的偏移量。
最后,在一个新的const
块中再次使用了iota
,它会被重置为 0,并在该块中继续递增。
通过这个示例,可以看到iota
的灵活性和在定义枚举或常量序列时的强大功能。
常量
在 Go 语言中,常量(Constants)是固定不变的值,它们在程序编译时被确定,并且在整个程序的执行过程中都不能被修改。常量可以是布尔值、数字(整数或浮点数)、字符串或枚举值。
常量的声明和初始化
在 Go 语言中,常量可以使用const
关键字进行声明。你可以在同一行声明多个常量,如果它们具有相同的类型。如果常量的类型没有明确指定,那么 Go 编译器会根据常量的值来推断其类型。
以下是一些常量声明的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main
import "fmt"
func main() {
// 声明并初始化单个常量
const Pi = 3.14159
// 在同一行声明多个相同类型的常量
const (
StatusOK = 200
StatusFound = 302
StatusBad = 400
)
// 使用 iota 进行递增的常量声明
const (
x = iota // x == 0
y // y == 1
z // z == 2
wp // 如果在这一行前没有显式赋值,则 wp 也会自增,wp == 3
)
// 显式赋值会改变 iota 的自增行为
const (
v = iota // v == 0
u = 100 // u == 100, iota 的自增被这个显式赋值打断了
vv = iota // vv == 1, iota 继续从上一个显式值开始自增
ww = "hello" // ww 是字符串类型,iota 的自增被打断
xx // xx 在这里会是一个新的 iota 值,但它不会被使用(因为没有赋值给它)
)
fmt.Println(Pi)
fmt.Println(StatusOK, StatusFound, StatusBad)
fmt.Println(x, y, z, wp)
// 注意:vv 和 ww 不会被打印,因为它们没有在这段代码中被使用
}
常量的类型
- 数值常量:可以是整数或浮点数。
- 布尔常量:可以是
true
或false
。 - 字符串常量:用双引号(
"
)或反引号(```)括起来的字符序列。反引号中的字符串会原样输出,不进行转义。
常量的特点
- 常量在声明时必须赋值。
- 常量一旦被声明,其值就不能再改变。
- 常量在编译时就已经确定,因此它们的值在运行时不会改变。
- 常量可以是任何基本数据类型,也可以是数组、结构体和切片的组合类型,但不能是函数、映射或通道类型。
iota 枚举
iota
是 Go 语言中的一个特殊常量,用于创建枚举值。在const
声明中,iota
会被自动赋值为 0,然后在每次新的const
声明中自增 1。iota
通常用于生成一组递增的整数常量。如上面示例中所示,你可以在同一行使用iota
为多个常量赋值,或者在不同的行中使用iota
来生成连续的整数常量。