3. 数据类型及变量
3. 数据类型及变量
数据类型
数据类型用于声明变量,虽然在函数中也有所涉及,如 参数、返回值等,但本质上仍是变量,如参数变量,返回值变量。
数据类型实际上是为了优化内存空间的占用而提出的概念,根据实际的数据需求,分配不同的数据类型,从而达到节约内存的作用。
Golang 中的数据类型分为:基本数据类型 和 复合数据类型。
基本数据类型
- 数值类型:整数类型
(int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64)
和浮点数类型(float32, float64)
、实数和虚数类型(complex64、complex128)
- 布尔类型:
bool
,Go 语言中不允许将布尔值类型强制转换为整型,也无法直接参与数值运算,也无法与其他类型转换。 - 字符串类型:
string
基本类型的值,直接存在变量中。
复合数据类型
- 数组类型:
[n]T
,表示拥有n
个类型为T
的元素的数组。数组是固定大小的连续内存块,其元素是存储在数组内存中的值,而不是地址。访问数组元素时,是直接访问内存中的数据。
var arr [3]int = [3]int{1, 2, 3}
- 切片类型:
[]T
,动态数组,可以增长和收缩。切片是一个动态数组,其底层结构包含一个指向数组的指针、长度和容量。切片本身包含了一个指向底层数组的指针,因此切片是通过地址引用数组元素的
var slice []int = []int{1, 2, 3}
- 映射类型:
map[K]V
,键值对集合。映射是一个哈希表,它是引用类型。映射中的键值对存储在内存中的某个位置,映射变量本身是一个指向哈希表的指针。
var m map[string]int = map[string]int{"a": 1, "b": 2}
- 结构体类型:
struct
,用于组织不同类型的字段。结构体是一个聚合数据类型,其字段是存储在结构体内存中的值,而不是地址。不过,结构体可以包含指针字段。
type Person struct {
Age int
Name string
}
var p person = Person{ 18, "CoderMast" }
- 指针类型:
*T
,用于声明一个指向类型 T 的指针。可使用&
取地址符来获取指定变量的地址,使用*
来取出指针所指向的地址的值。在 32 位系统上,指针为 4B,在 64 位系统上,指针为 8B。
var i int = 10
var p *int = &i
var j int = *p
具体的变量信息如下:
内存地址: 变量: 值:
0x0000 i 10
0x0004 p 0x0000(指向 i 的地址)
0x000C j 10
- Channel 类型,管道类型,用于在 goroutine 之间进行通信,从而控制 goroutine 的执行。操作符为
<-
。var ch chan ChannelType
用于声明一个 channel 类型的变量 ch,且仅接受 ChannelType 类型的数据。
ch := make(chan int) // 定义一个仅接受 int 类型的管道变量 ch
ch <- 10 // 写入管道
i := <- ch // 读出管道
管道中的值,读出即失效。
- 函数类型,在 Golang 中函数可像普通变量一样被传递、赋值和作为参数或者返回值。
// 1. 函数类型声明
type Operator func(int, int) int
// 2. 函数类型赋值
func add(a int,b int) int {
return a + b
}
var operator Operator
operator = add
综上所述,在 Go 语言中
- 数组元素直接存储在数组的内存块中。
- 切片是引用类型,通过指针引用底层数组。
- 映射是引用类型,通过指针引用底层哈希表。
- 结构体字段直接存储在结构体内存块中,但结构体可以包含指针字段。
这意味着在使用切片和映射时,实际操作的是底层数据的地址,而数组和结构体的操作是对其内存块中实际存储的数据进行操作。
变量
在计算机中,数据都是存在内存中的二进制序列,可直接通过内存地址进行数据访问,但直接操作内存地址,不仅难度高、效率低,而且可能造成极其危险的后果,为了解决这个问题,引入了变量的概念,通过变量来访问数据。实际上变量的定义来源于数学,意思为可变化的量,通过变量名来访问变量的值。
在 Golang 中变量可通过 var 关键字来声明,具体语法如下:
- 变量的声明
// 1. 声明单个变量
var variableName type
// 2. 同时声明多个变量
var variableName1,variableName2 type
该示例定义了一个数据类型为 type
,变量名为 identifier
的变量。
该示例定义了两个数据类型为 type
,变量名为 variableName1
和 variableName2
的变量。
- 变量的初始化
// 1. 初始化单个变量
var name string = "友人"
// 2. 一次性初始化多个变量
var name, age = "CoderMast", 18
Golang 提供了类型推导,可使得在不显式声明数据类型时,可直接初始化变量。
var name = "GolangNotes"
另外,Golang 还提供了一种简化变量声明和初始化的语法糖,可直接定义并初始化变量,已经被定义的变量无法使用该语法糖。
name := "CoderMast"
变量声明后如果没有给定初始值,则 Go 会默认给定对应的 零值,这里的零值并非等于 0,而是代指默认值。
常量
变量是变化的量,那么常量即为不变的量,实际上就是这样。Golang 中常量和变量类似,只需要使用 const 关键字即可。
// 单个变量
const url = "https://www.golangnotes.com/"
// 多个变量
const (
name = "CoderMast"
age = 18
)
// 同时声明多个常量时,如果省略了值则表示和上面一行的值相同
const (
n1 = 100
n2
n3
)
iota
iota 是 Golang 中的一个特殊常量,可以被编译器修改。是 golang 中的常量计数器,在第一次使用 const 声明常量时初始化为 0,之后每声明一个常量则将 iota 加 1,也可将 iota 看做是常量的索引。
const (
i = iota
j = iota
k = iota
)
// fmt.Println(iota) 这样是错误的,不能直接把 iota 当做变量或常量使用
fmt.Println(i)
fmt.Println(j)
fmt.Println(k)