变量的声明方式
声明变量的一般形式是使用 var
关键字,有以下使用方法
-
指定变量类型,声明后若不赋值,使用默认值。
1
var var_name var_type
-
根据值自行判定变量类型(类型推导)
1
var v_name = value
-
省略
var
, 使用初始化声明:=
:=
左侧的变量不应该是已经声明过的,否则会导致编译错误。- 在定义变量 a 之前使用它,则会得到编译错误 undefined: a。
- 声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误
- 只可以在函数内使用,不能用于声明全局变量
|
|
示例代码
|
|
-
多变量声明方式
-
对于全局变量可以采用分解的方式来一次性声明
1 2 3 4 5
var x, y int var ( // 分解的写法,一般用于声明全局变量 a int b bool )
-
也可以直接使用单变量的三种方式
1 2 3
var c, d int = 1, 2 var e, f = 123, "liudanbing" g, h := 123 //只能在函数体内使用
-
基本数据类型
Go的数据类型分类与Java类似分为基本数据类型和派生数据类型
- 基本数据类型
- 数值型
- 整数型
- 浮点型
- 字符型(没有专门的字符型,使用
byte
来保存字符) - 布尔型:
bool
- 字符串:
String
- 数值型
- 派生数据类型
- 指针
- 数组
- 结构体
- 管道
- 函数
- 切片
- 接口
- map
数值型
整数型
整数型用于存储整数数值
有符号整数
类型 | 有无符号 | 占用存储空间 | 数据范围 |
---|---|---|---|
int8 | 有 | 1个字节 | $-128$~$127$ |
int16 | 有 | 2个字节 | $-2^{15}$~$2^{15}-1$ |
int32 | 有 | 3个字节 | $-2^{31}$~$2^{31}-1$ |
int64 | 有 | 4个字节 | $-2^{63}$~$2^{63}-1$ |
无符号整数
类型 | 有无符号 | 占用存储空间 | 数据范围 |
---|---|---|---|
uint8 | 无 | 1个字节 | $0$~$255$ |
uint16 | 无 | 2个字节 | $0$~$2^{16}-1$ |
uint32 | 无 | 3个字节 | $0$~$2^{32}-1$ |
uint64 | 无 | 4个字节 | $0$~$2^{64}-1$ |
其他整数类型
类型 | 有无符号 | 占用存储空间 | 数据范围 | 注意事项 |
---|---|---|---|---|
int | 有 | 32位系统4个字节64位系统8个字节 | $-2^{31}$~$2^{31}-1$(32位系统) $-2^{63}$ ~$2^{63}-1$(64位系统) |
|
uint | 无 | 32位系统4个字节64位系统8个字节 | $0$ $0$ |
|
rune | 有 | 3个字节 | $-2^{31}$~$2^{31}-1$ | 等价 int32,表示一个 Unicode 码 |
byte | 无 | 1个字节 | $0$~$255$ | 当要存储字符时选用byte |
Golang中的默认整数类型为 int
浮点数型
类型 | 占用存储空间 | 表数范围 |
---|---|---|
float32 | 4字节 | |
float64 | 8字节 |
注意事项
- Golang 浮点类型有固定的范围和字段长度,不受具体 OS(操作系统)的影响。
- Golang 的浮点型默认声明为
float64
类型。
字符型
Golang 中没有专门的字符类型,如果要存储单个字符(字母),一般使用 byte
来保存。字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。也就是说对于传统的字符串是由字符组成的,而Go的字符串不同,它是由字节组成的。
Go中的字符型使用 byte
来保存,字符使用 ' '
括起来
|
|
可以使用转义字符将字符变成特殊字符常量,常见的转义字符如下
\t
:制表符\n
:换行符\r
:一个回车
注意事项
- Go的字符采用UTF-8编码,字符本质上是一个整数,直接输出时是输出字符的UTF-8码值
- 使用格式化输出
%c
才能输出字符值
布尔类型
布尔类型使用 bool
存储,大小为1个字节,只允许值为 true
和 false
字符串类型
字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。字符串的编码为UTF8 ,源代码中的文本字符串通常被解释为采用 UTF8 编码的 Unicode 码点(rune)序列。因此字符串可以包含任意的数据
底层原理
|
|
注意事项
- 在Go中字符串是不可变的,类似Java
- 表示方法
- 使用双引号
“ ”
表示字符串会识别转义字符 - 使用反引号
· ·
以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击、输出源代码等效果
- 使用双引号
- 字符串之间使用
+
进行拼接 - 对于长字符串使用分行拼接处理,将
+
保留在上一行
作用域
Go 语言中变量可以在三个地方声明
- 函数内定义的变量
- 函数外定义的变量
- 函数定义中的变量
作用域分为以下几种
- 局部变量:在函数体内声明的变量的作用域只在函数体内,参数和返回值变量也是局部变量
- 全局变量:在函数体外声明的变量可以在整个包甚至外部包(被导出后)使用可以在任何函数中使用
- 形式参数:形式参数会作为函数的局部变量来使用
基本数据类型的默认值
在 go 中,数据类型都有一个默认值,当没有赋值时,就会保留默认值,在go 中,默认值又叫零值。
数据类型 | 默认值 |
---|---|
int | 0 |
float | 0 |
string | "" |
bool | false |
基本数据类型之间的相互转换
Go和Java不同,Go不支持数据类型的自动转换需要显式自动转换
语法格式
|
|
基本数据类型和string之间的转换
基本数据类型转string
fmt.Sprintf("%参数",表达式)
- 使用
strconv
包中的函数func FormatBool(b bool) string
func FormatInt(i int64,base int) string
func FormatFloat(f float64,fmt byte,prec,bitSize int) string
string转基本类型
- 使用
strcov
包中的函数func ParseBool(str string) (value bool, err error)
func ParseFloat(s string, bitSize int) (f float64,er error)
func Parselnt(s string, base int, bitSize int) ( int64,err error)
func ParseUint(s string, b int, bitSize int) (n uint64 err error)
指针
类似于C++,Go保留了指针
指针保存了值的内存地址,其零值为 nil
。
- 取址符:
&
操作符生成一个指向其操作数的指针,获取地址。 - 解引用:
*
操作符表示指针指向的底层值。
结构体
一个结构体(struct
)就是一组 字段(field)。
|
|
Go的结构体支持匿名字段,用于在一个结构体中插入另一个结构体,可以用于模拟实现继承行为
结构体常通过指针传递,避免复制整个结构体,提高性能。
虽然 Go 本身语法中没有类似 Java 中的 @Annotation
的注解机制,但结构体字段可以使用反引号(`)添加 tag,以传递元信息(meta info)给反射或其他工具使用。
- 标签必须用 反引号(`) 包裹。
- 每个 tag 是
key:"value"
形式,多个 tag 之间以空格分隔。 - 每个 key 应唯一。
|
|
type关键字
在 Go 语言中,type是一个重要而且常用的关键字。它可以用于定义结构体、类型别名、方法等。
可以用于定义类型别名
|
|
在编译的时候,类型别名会被直接替换成对应类型。
可以用于类型判断
|
|
数组
类型 [n]T 表示一个数组,它拥有 n
个类型为 T
的值。
声明方法
|
|
存储特点
- 数组的长度是其类型的一部分,因此数组不能改变大小。
- 数组元素类型相同
- 数组在内存中连续存储
- 如果数组长度不确定,可以使用
...
代替数组的长度,编译器会根据元素个数自行推断数组的长度 - 数组是值类型,并不是隐式的指向第一个元素的指针(比如 C 语言的数组),而是一个完整的值赋值和传参会复制整个数组
遍历方式
使用 range
循环进行遍历,其中第一个返回值为数组下标,第二个返回值为数组值
|
|
值数据类型和引用数据类型
数据类型分为值数据类型和引用数据类型
- 值数据类型:这种类型的变量直接指向存在内存中的值
- 引用数据类型:这种类型的变量存储的是变量所在的内存地址
常见的值数据类型有
- 布尔:bool
- 字符串:string
- 数值型
- 有符号整数
int
int8
int16
int32
int64
- 无符号整数
uint
uint8
uint16
uint32
uint64
uintptr
- 字符型:
byte
// uint8 的别名 rune
// int32 的别名,表示一个 Unicode 码位- 浮点型
float32
float64
- 虚数
complex64
complex128
- 有符号整数
- 数组
- 结构体
常见的引用数据类型
- 指针
- 切片
- 映射
常量
常量是一个简单值的标识符,在程序运行时,不会被修改的量。
定义
常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
|
|
- 其中type可以省略,go可以通过类型推断
- 常量不能用
:=
语法声明。
自增长
在 golang 中,一个方便的习惯就是使用 iota
标示符,它简化了常量用于增长数字的定义,给以上相同的值以准确的分类。
|
|
底层原理:当你在一个 const
组中仅仅有一个标示符在一行的时候,它将使用增长的 iota
取得前面的表达式并且再运用它
类型系统
组成部分
- 基本类型: 包括整数类型(如
int
、int8
、int16
等)、浮点数类型(如float32
、float64
)、布尔类型(bool
)、字符串类型(string
)等。 - 复合类型:
- 数组:具有固定长度的相同类型元素的序列。
- 切片:可以动态增长或收缩的元素序列。
- 结构体:将不同类型的数据组合在一起形成一个新的类型。
- 指针:用于指向其他变量的地址。
- 映射(字典):存储键值对的数据结构。
- 接口类型: 定义了一组方法签名,具体的类型可以实现这些接口。
- 类型别名: 可以为已有的类型定义一个新的名称。
接口
在 Go 语言中,接口(interface) 是一种抽象类型,定义了一组方法的集合,只要某个类型实现了这些方法,就自动满足这个接口 —— 无需显式地声明“我实现了某个接口”。
定义接口
|
|
实现接口
只要某个类型实现了接口中定义的所有方法,它就自动实现了该接口。
|
|
使用接口
|
|
应用场景
interface{}
是 空接口 ,可以接受任何类型的值 ,常用于处理未知类型(如:fmt.Println
、JSON 解析、泛型前的容器类型)。- 接口断言是 从接口值中 提取具体类型,可用于判断类型
|
|
类型元数据
不管是内置类型还是自定义类型都有对应的类型描述信息,称为它的 “类型元数据”。而且每种类型的元数据都是全局唯一的,这些类型元数据构成了 Go 语言的 “类型系统”
每个类型元数据的 Header被放到了 runtime._type
结构体
|
|
在 _type
之后存储的是各种类型额外需要描述的信息 例如 slice 的类型元数据在 _type
结构体后面记录着一个 *type
,指向其存储的元素的类型元数据。如果是 string 类型的 slice,下面这个 *_type
类型的指针就指向 string 类型的元数据。
如果是自定义类型,在其它描述信息的后面还会有一个 uncommontype 结构体。
|
|