数据类型
Go语言中,数据类型用于声明函数参数和变量,这篇笔记我们介绍Go语言中的数据类型相关的概念。
数据类型种类
Go语言是强类型语言,声明的每个变量都需要绑定到特定的数据类型,并且它只接受与此类型匹配的赋值。Go语言数据类型分为两大类,值类型(Value Types)和引用类型(Reference Types)。
- 值类型
- 基本类型:布尔,字符串,数字(整数、浮点数、复数)
- 复合类型:数组,结构体
- 引用类型:变长数组(slice),字典(map),通道(Channel),接口,函数
对于引用类型,它存储的是指向数据的地址而不是数据本身,当引用类型的变量被赋值或作为函数参数传递时,实际上是将该地址进行了复制,它们实际指向的可能是同一份数据。
基本数据类型
Go语言中有如下基本类型。
bool
string
int int8 int16 int32 int64 // int类型长度取决于CPU字长
uint uint8 uint16 uint32 uint64 uintptr // 和int相同,uint长度取决于CPU字长
byte // uint8的别名
rune // int32的别名,通常用于代表一个Unicode码
float32 float64
complex64 complex128 // 复数类型
这里注意,关于何时用int何时用int32此类问题,和C/C++是一样的,如非特殊需求我们就应该用int,编译器会对目标平台进行优化,选择合适的数据类型;而网络传输、二进制格式读写等,则必须要用类似int32等确定类型。
指针
Go语言中的指针和C/C++类似,代表变量在内存中的地址。在特定的情况下,我们应该选用指针,以实现引用传递,或是减少内存拷贝开销。
Go指针和C/C++写法类似,我们可以使用取地址符&获取一个变量的指针,使用解引用符*获取指针指向的变量,不过区别是Go语法都是倒着写的,指针也是类似*int的形式。
var i int = 0
var iPtr *int = &i // 声明指针并赋值
var j int = *iPtr // 指针解引用
指针能够实现引用传递,如果作为函数参数传入,我们可以修改参数指针指向的内存地址,下面代码我们使用指针传递了一个int类型的变量。
package main
import "fmt"
func foo(i *int) {
*i = 1
}
func main() {
var i int = 0
foo(&i)
fmt.Printf("%v", i)
}
最终i的值为1。
type关键字
type创建全新类型
Go语言中,type关键字可以基于已有类型创建全新的独立类型,它的意义在于能让我们创建新类型并附加方法。下面例子中,我们想创建一个摄氏度Celsius类型,它本质还是float64,然而我们不能直接给float64添加方法,此时type关键字就派上用场了。
type Celsius float64
func (c Celsius) ToFahrenheit() float64 {
return float64(c)*9/5 + 32
}
代码中,虽然看起来我们创建的Celsius类型就是float64,但Go语言中它们被视为不同类型,不能隐式转换,这和C/C++中的typedef是不同的。
type起别名
type关键字的另一种方式是给类型起别名,相比之前的创建全新类型,这种使用方式才类似C/C++的typedef。
type dataLength = int32
var i dataLength = 0
当然,个人不建议使用type关键字定义一大堆令人迷惑的别名,这会严重降低代码的可读性和可扩展性。