数据类型

值类型和引用类型

在golang中,同其他语言相同,可以将类型大致分为两类:值类型引用类型


其中,值类型存储在栈中,他们在编译期就可以确定变量所占用的空间,并且值类型变量直接指向栈空间的值。使用等号=将一个变量的值赋给另一个变量时,如j = i,实际上是在内存中将 i 的值进行了拷贝。我们可以通过 &i 获取变量 i 的内存地址。在golang中,属于值类型的数据类型包含:

  • 数字类型

  • 布尔类型

  • 字符串类型

  • 数组:数组也存放在栈空间中,这个与Java不同

  • 结构体:因为是值传递,所以在方法之间传递会进行值复制,如果结构体较大,需要使用指针


引用类型拥有更复杂的存储结构,推崇存储在堆内存中,编译时一般无法确定其所占空间:

  1. 需要通过make创建并分配内存

  2. 初始化一系列属性:指针、长度、哈希分布、数据队列等。一个引用类型的变量r1存储的是r1的值所在的内存地址(数字),或内存地址中第一个元素所在的位置,这个内存地址被称之为指针,这个指针实际上也被存在另外的某一个变量中。

在golang中,是引用类型的有:

  • 指针

  • 管道 channel

  • 接口 interface

  • 映射 map

  • 函数 function


**值类型在传递参数时,进行值拷贝,引用类型则是引用拷贝。**主要是赋值的区别。

类型零值

零值也就是默认值,当一个类型声明之后没有被初始化,那么他的值就是零值,每种类型都有对应的零值,其中,引用类型对应的零值都为nil

数据类型
零值

数字类型,包含整型、浮点型、复数

0

布尔型

false

字符串

""

结构体

结构体中的每个字段都是零值

引用类型:slicepointermapchannelfunctioninterface

nil

nil详解

在Go语言中,布尔类型的零值(初始值)为 false,数值类型的零值为 0,字符串类型的零值为空字符串"",而指针、切片、映射、通道、函数和接口的零值则是 nil

注意,nil是一个值,像0一样,代表不存在

注意,使用nil,要注意下面几点:

  • 不是关键字和保留字

    因为不是关键字和保留字,只是一个标识符,类似int等,所以可以定义一个名称为nil的变量:

  • 没有默认类型

  • 引用类型的零值(初始值)都是nil

  • 不同引用类型的nil值,指针是相同的

  • 不同引用类型的nil值,占用大小不同

  • 两个nil字面量比较

  • 两个值都为nil的变量不可比较

  • 变量(有可能是nil 或者 非nil)可以与nil值比较:

基本数据类型

数值型

整型

无符号整型

数据类型
存储空间(字节)
值范围
数据级别
默认值

uint8

1

0 ~ 255

0

uint16

2

0 ~65535

6万多

0

uint32

3

0 ~ 4294967295

40多亿

0

uint64

4

0 ~ 18446744073709551615

大到没有概念

0

uint

系统决定,无符号整型

32位系统位int32,64位系统位int64

0

有符号整型

数据类型
存储空间(字节)
值范围
数据级别
默认值

int8

1

-128 ~ 127

正负百

0

int16

2

-32768 ~ 32767

正负3万多

0

int32

3

-2147483648 ~ 2147483647

正负大20多亿

0

int64

4

-9223372036854775808 ~ 9223372036854775807

正负大到没有概念

0

int

系统决定,有符号整型

32位系统位int32,64位系统位int64

0

字符整型

数据类型
存储空间(字节)
作用

byte

uint8的别名

用与表示一个ASCII

rune

int32的别名

用于表示一个Unicode代码点

表示一个ASCII:

表示一个Unicode代码点:

浮点型

数据类型
存储空间(字节)
值范围
数据级别
默认值

float32(不常用)

3

IEEE-754 1.401298464324817070923729583289916131280e-45 ~ 3.402823466385288598117041834516925440e+38

精度6位小数

0

float64

4

IEEE-754 4.940656458412465441765687928682213723651e-324 ~ 1.797693134862315708145274237317043567981e+308

精度15位小数

0

复数

我们把形如 z=a+bi(a、b均为实数)的数称为复数。其中,a 称为实部,b 称为虚部,i 称为虚数单位。当 z 的虚部 b=0 时,则 z 为实数;当 z 的虚部 b≠0 时,实部 a=0 时,常称 z 为纯虚数。复数域是实数域的代数闭包,即任何复系数多项式在复数域中总有根。

复数的运算:

  • 加法法则:(a+bi)+(c+di)=(a+c)+(b+d)i`

  • 减法法则:(a+bi)-(c+di)=(a-c)+(b-d)i`

  • 乘法法则:(a+bi)(c+di)=(ac-bd)+(bc+ad)i

  • 除法法则:img

数据类型
存储空间(字节)
默认值

complex64

8

(0+0i)

complex128

16

(0+0i)

复数的值由三部分组成 RE + IMi,其中 RE 是实数部分,IM 是虚数部分,REIM 均为 float 类型,而最后的 i 是虚数单位。

复数的定义和运算:

布尔型

数据类型
存储空间(字节)
值范围
默认值

bool

1

true,false

false

字符串

  • 字符串是一个不可变的UTF-8字符序列,并且每个属于ASCII码的字符占用单个字节,其他字符则是占用2-4个字节

  • 不同于C、C++、Java,他们的UTF-8字符长度至少会占用两个字节

  • Go语言这样做不仅减少了内存和硬盘空间占用,同时也不用像其它语言那样需要对使用 UTF-8 字符集的文本进行编码和解码

  • 双引号字符串支持转义字符

访问字符

字符拼接 "+"

多行字符串

多行字符串中的内容都会原样输出,转义字符不会生效。通常用语内嵌代码或者数据

输出结果为:

类型转换

数值类型相互转换

基本类型 -> string

string->基本类型

派生数据类型

派生数据类型又称为复合数据类型,是由基本类型复合而来。

指针

基本类型也有对应的指针类型

通过&创建指针变量

通过*获取指针变量对应的值

改变指针变量指向的值

通过new()函数创建指针变量

数组

定义数组

下标访问

遍历数组:for

遍历数组:for range

数组比较

必须保证数组类型长度相同,才能进行数组比较:

多维数组

切片

image-20210910171851698
  • 切片是对数组连续片段的引用

  • 这个片段可以是整个数组,也可以是指定起始位置的子集

  • 切片内部主要包括三个部分

    • data,指向切片所在数组的开始元素位置的指针

    • len,切片的长度

    • cap,切片的容量(底层数组的长度)

定义切片:从已有数组生成

从开始切到结尾

从指定位置切到结尾

从开始切刀指定位置

重置切片:空切片

定义切片:直接定义

切片声明与数组声明很像,只不过切片的声明没有长度;这种方式声明切片与make()函数效果一致,底层都会创建一个不可访问的数组

定义切片:使用make()函数构造切片

切片容量:cap()

切片长度:len()

添加元素:append()

  • 在使用 append() 函数为切片动态添加元素时,如果空间不足以容纳足够多的元素,切片就会进行“扩容”,此时新切片的长度会发生改变

  • 切片在扩容时,容量的扩展规律是按容量的 2 倍数进行扩充,也就是扩容因子为2

复制:copy()

复制需要保证切片类型一致

删除元素

切片的删除实际上仍然是根据当前切片切割,比如删除头部元素:

删除中间位置:

删除尾部元素:

遍历切片:range

多维切片

映射

map,键值对映射结构,一种元素对(pair)的无序集合,pair 对应一个 key(索引)和一个 value(值),所以这个结构也称为关联数组或字典,这是一种能够快速寻找值的理想结构,给定 key,就可以迅速找到对应的 value

  • key不可以重复

  • key的类型不能是:slicemapfunction

  • value的不做限制

定义map

遍历map: range

添加/更新键值对

删除键值对: delete()

清空map

go没有提供清空map的方法,有两种方法可以清空map:

  • 遍历调用delete()

  • 给变量重新赋予一个新创建的map

结构体

结构体的定义只是一种内存布局的描述,只有当结构体实例化时,才会真正地分配内存。

定义结构体

type用于自定义类型,定义type可以对结构体进行复用

同类型变量可将字段放在一行

空结构体,没有意义

字段类型不受限制

结构体的字段类型不受限制,可以是基本类型,也可以是复合类型,比如函数等:

实例化结构体

基本实例化形式

实例化指针类型结构体(常用)

取地址符的实例化(常用)

对结构体进行&取地址操作时,视为对该类型进行一次 new 的实例化操作

初始化结构体

键值类型初始化

多值列表初始化

  1. 字段顺序要保持一致

  2. 所有字段必须要初始化

匿名结构体的初始化

管道

参见:并发编程/channel

函数

接口

参照:面向对象/接口

类型定义

无论是类型还是类型别名,都可以为他们指定方法

类型别名

类型别名是Go1.9版本添加的新功能,主要用于解决代码升级、迁移中存在的类型兼容性问题。再重构、升级代码时,经常会遇到变量名称变更,C/C++选择使用宏快速定义一段新的代码,而Golang则使用类型别名:

定义类型别名:

无论是类型还是类型别名,都可以为他们指定方法

最后更新于

这有帮助吗?