Go语言数据类型包括整型(int)、浮点型(float32、float64)、布尔型(bool)、字符(byte、rune)、字符串(string)、切片([]T)、结构体(struct)、函数(func)、映射(map)、通道(channel)、指针(*T)等。其中整型、浮点型、布尔型、字符、字符串为go语言的原生数据类型,这几种类型也是本篇文章将分享的内容,其他数据类型涉及内容较多,会在后续的文章中单独分享。
按长度可分为:int8、int16、int32、int64
还有对应的无符号整型(可以理解为数学中的自然数):uint8、uint16、uint32、uint64
其中,uint8对应的是byte型,int16对应c语言的short型,int64对应c语言的long型
在go语言中,有可以自动匹配特定平台的整型长度的类型——int和uint。
注意:因为int和uint会自动匹配平台,所以在使用int和uint类型时,不能假定它是32位或是64位的整型,而是考虑int和uint在不同平台上的差异。
为什么需要自动匹配平台?
go语言可以跨平台运行在多种平台上,而不同的平台的字节长度是有差异的,目前64位平台已较为普及,但是8位、16位和32位的操作系统依旧存在。虽然16位平台上依然可以使用64为的变量,但运行性能和内存性能上会比较差。同理,在64位平台上大量使用8位、16位等与平台位数不等长的变量时,性能也会比较差。因此,为了在各个平台上获得最好的性能,就需要实现自动匹配不同的平台。
如何自动匹配?
go语言是通过编译器来实现平台的自动匹配的,在编译过程中,编译器会尽量将内存对齐目标平台的位数,以便获取最好的性能。这也说明了自动匹配并不是由go运行时实现的,所以为了获取最好的性能,在发布到不同平台前需指定不同的编译条件,以便生成特定平台的编译文件。
// 声明不同长度的int类型
var (
a int
b int8
c int16
d int32
e int64
)
go语言支持两种浮点型:float32 和 float64,float32的最大范围约为3.4e38, float64最大范围约为1.8e308
// 声明不同精度的浮点型
var (
a float32
b float64
)
布尔型在go语言中以bool类型进行声明,只有true和false两个值,在go语言中不允许将整型强制转换为布尔型(有些语言可以,如:Object-c)
// 声明布尔型
var a bool
a = true
if a {
println(a)
}
// 不允许将整型强制转换为布尔型
// var b = 1
// if b {
// println(b)
// }
// 不运行布尔型强制转换为整型
// println(int(a))
4.1、字符串在go语言中以原生数据类型出现,使用字符串就像使用其他原生数据类型(如:bool、int、float32、float64等)一样。在其他大部分语言中,string并不是以原生数据类型存在的,比如:在c#语言中,字符串并不是以原生数据类型出现,而是以类的方式进行封装。
// 声明string变量并初始化
var a = "abcd"
var b = "这是中文"
4.2、go语言字符串实现基于UTF-8编码,其内部实现使用UTF-8编码,通过rune类型,可以方便地对每个UTF-8字符串进行访问,也支持按传统的ASCII码方式进行逐字符访问。
// 声明string变量并初始化
var a = "abcd"
var b = "这是中文"
// 将string 转换为rune 切片
var e = []rune(a)
var f = []rune(b)
// 将string 转换为byte 切片
var g = []byte(a)
var h = []byte(b)
// 获取第一个字符并转为string输出
println(string(e[0]))
println(string(f[0]))
println(string(g[0]))
println(string(h[0]))
/*
输出结果:
a
这
a
è
*/
注意:根据以上示例,可以很清楚的看到rune可以很轻松的处理包括中英文的字符串,但是byte类型在处理中文时输出结果会出现乱码的情况。这是因为byte对应的是ASCII,而中文并不在ASCII范围内,在转换过程中截取分组时会出现对位错误,从而出现乱码,所以在实际开发中需要多注意。
4.3、go语言中的转义字符和其他语言中的转义字符并没有什么差异,具体如下:
\r 回车符(返回行首)
\n 换行(直接跳到下一行的同列位置)
\t 制表符
\' 单引号
\" 双引号
\\ 反斜杠
// 声明string变量并使用转义字符\\
var c = "C:\\Users\\kenny\\Desktop\\MyFirstGo"
4.4、go语言可以使用“`’”反引号书写多行字符串
// 声明多行字符串
var d = `
第一行
第二行
第三行
`
字符串中的每一个元素叫做"字符", go语言的字符有两种:
一种是utf8类型,或者叫byte型,代表了ASCII码的一个字符,tyte类型实际上是int8。
另一种是rune类型,代表UTF-8字符,当需要处理中文、日文或者其他复合字符时使用,rune类型实际上是一个int32。
// 声明rune类型
var a rune = 'a'
var b rune = '你'
// 声明byte类型
var c byte = 'c'
// byte 不能处理超过ASCII范围的字符
// var d byte = '你'
转换格式如下:T(表达式),其中T为需要转换的类型,表达式包括变量、算式、函数返回值等
// 声明int类型
var a = 10
// 声明float32类型
var b float32 = 1.22
// 声明rune类型
var c rune = 'a'
// 声明byte类型
var d byte = 'b'
// 输出原数据结果
println("================原数据结果=====================")
println(a, b, c, d)
// 转换数据类型
e, f, g, h := float32(a), int(b), string(c), string(d)
// 输出转换后结果
println("================转换后结果=====================")
println(e, f, g, h)
/*
================原数据结果=====================
10 +1.220000e+000 97 98
================转换后结果=====================
+1.000000e+001 1 a b
*/
从输出结果可以看出:
int类型正常的转换为了float32类型
float类型也转换成了int的类型,不过精度会丢失,这个开发过程中需注意
rune和byte类型均正常转换成了string类型
在go语言中指针概念被拆分为两个核心概念
类型指针,允许对这个指针类型的数据进行修改。传递数据使用指针,而无需拷贝数据,类型指针不能发生偏移和运算。
切片,由指向其实元素的原始指针、元素数量和容量组成。
受益于这样的约束和拆分,go语言的指针类型变量拥有指针的高效访问,但又不会发生指针偏移,从而避免非法修改关键性数据问题。同时,垃圾回收也比较容易对不会发生偏移的指针进行检索和回收。切片比原始指针具备更强大的特性,更为安全,当切片发生越界时,运行时会宕机并打出堆栈,而原始指针不会。
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。go语言和c语言一样使用“&”操作符进行变量的取址操作。
格式如下:
ptr := &v
v 代表被取址的变量,ptr的类型为“*T”,称作T的指针类型,“*”代表指针
使用“*”对指针地址进行取值
格式如下:
value := *ptr
value代表取得的指针的值,*在这里是取址操作符,ptr代表的是指针
示例:
// 声明两个整型变量
a, b := 1, 2
// 使用取址操作符获得变量a和b的指针
aptr := &a
bptr := &b
// 使用取值操作符交换变量a和b的值
// 临时取出指针aptr的值存放在变量t
t := *aptr
// 将指针bptr的值赋值给aptr
*aptr = *bptr
// 将变量t的值赋值给bptr
*bptr = t
println(a, b)
// 输出结果为:2 1