1. Go语言数据类型
1.1 数据类型分类
Go语言数据类型大致可以分为两类
基础类型,其中就包括了我们最常见的一些类型
类型 名称 长度 零值 说明 bool 布尔类型 1 false 其值不为真即为家,不可以用数字代表true或false byte 字节型 1 0 uint8别名 rune 字符类型 4 0 专用于存储unicode编码,等价于uint32 int, uint 整型 4或8 0 32位或64位 int8, uint8 整型 1 0 -128 ~ 127, 0 ~ 255 int16, uint16 整型 2 0 -32768 ~ 32767, 0 ~ 65535 int32, uint32 整型 4 0 -21亿 ~ 21 亿, 0 ~ 42 亿 int64, uint64 整型 8 0 float32 浮点型 4 0.0 小数位精确到7位 float64 浮点型 8 0.0 小数位精确到15位 complex64 复数类型 8 complex128 复数类型 16 uintptr 整型 4或8 ⾜以存储指针的uint32或uint64整数 string 字符串 "" utf-8字符串 复合类型, 这些类型构成了Go语言的特点
- 指针 (pointer)
- 数字 (array)
- 切片 (slice)
- 字典(map)
- 通道 (chan)
- 结构体 (struct)
- 接口 (interface)
2. 布尔类型
- 也叫做bool类型
- bool 类型数据的值只能是true 或者 false
- bool 类型默认值是false
- bool 类型 占1个字节
- bool类型一般用于流程控制
- bool类型不能接受其他类型赋值
- bool类型不支持自动或者强制类型装换
package main
import "fmt"
var a bool
func main() {
//a = 1 // 错误 cannot use 1 (type int) as type bool in assignment
fmt.Printf("type = %T\n", a)
fmt.Printf("value = %v\n", a)
if a {
fmt.Println("this is true")
} else {
fmt.Println("this is false")
}
}
type = bool
value = false
this is false
3. 整数类型
整数类型就是存放整数值得
int类型和uint类型自动匹配平台长度
类型 有无符号 占用空间 范围 备注 int 有 32位系统4个字节<br />64位系统8个字节 <br /> uint 无 32位系统4个字节<br />64位系统8个字节 <br /> rune 有 与int32一样 等价int32,表示一个Unicode码 byte 无 与uint8等价 0~255 存储字符使用 Go语言的整型默认声明是int型
通常int和int32被认为是两种不同的类型,编译器不会做自动装换
整数类型可以进行数值运算 (加减乘除和求余)
整数类型可以进行比较运算(> , < ,==, >= , <= ,!=)
两个不同类型的整数不能比较,即使他们的值看着相同也不行
3.1 查询某个变量的字节大小和数据类型
package main
import (
"fmt"
"unsafe"
)
var v1 int8
var v2 int16 = 88
var v3 int32 = 8978923
var v4 = 8978989
var v5 int64
var v6 rune
func main(){
fmt.Printf("v1 类型是%T, v1 占的字节数是%d\n",v1,unsafe.Sizeof(v1))
fmt.Printf("v2 类型是%T, v2 占的字节数是%d\n",v2,unsafe.Sizeof(v2))
fmt.Printf("v3 类型是%T, v3 占的字节数是%d\n",v3,unsafe.Sizeof(v3))
fmt.Printf("v4 类型是%T, v4 占的字节数是%d\n",v4,unsafe.Sizeof(v4))
fmt.Printf("v5 类型是%T, v5 占的字节数是%d\n",v5,unsafe.Sizeof(v5))
fmt.Printf("v6 类型是%T, v6 占的字节数是%d\n",v6,unsafe.Sizeof(v6))
}
v1 类型是int8, v1 占的字节数是1
v2 类型是int16, v2 占的字节数是2
v3 类型是int32, v3 占的字节数是4
v4 类型是int, v4 占的字节数是8
v5 类型是int64, v5 占的字节数是8
v6 类型是int32, v6 占的字节数是4
3.2 如何证明int和int64不是同一种类型
package main
import (
"fmt"
"unsafe"
)
var v1 = 99
var v2 int64
func main(){
fmt.Printf("v1的类型是%T,v1占的字节长度是%d\n",v1,unsafe.Sizeof(v1))
fmt.Printf("v2的类型是%T,v2占的字节长度是%d\n",v2,unsafe.Sizeof(v2))
// 将v1的值赋给v2
//v2 = v1 // 错误 cannot use v1 (type int) as type int64 in assignment
v2 = int64(v1) // 通过
fmt.Printf("v2的值是%v,v2的类型是%T",v2,v2)
}
v1的类型是int,v1占的字节长度是8
v2的类型是int64,v2占的字节长度是8
v2的值是99,v2的类型是int64
3.3 不同的整数类型不能比较
package main
import "fmt"
var a int32
var b int64
func main(){
a,b=8,8
if a == b{ //invalid operation: a == b (mismatched types int32 and int64)
fmt.Println("===")
}
}
4. 浮点型
浮点型用于表示包含小数点的数据,例如 1.234 , 0.99 , -9.9等就是一个浮点型数据,Go语言中的浮点型采用 IEEE-754 标准的表达方式
Go语言定义两个浮点类型float32和float64,其中float32相当于C语言中的float类型, float64等价于C语言中的double类型
类型 占用存储空间 范围 单精度float32 4字节 -3.4028234663852886e+38~3.4028234663852886e+38 双精度float64 8字节 -1.7976931348623157e+308~1.7976931348623157e+308
4.1 浮点数 = 符号位+指数位+尾数位
4.2 浮点数都是有符号的
package main
import "fmt"
func main(){
var p float32 = 99.99
fmt.Println(p)
var p1 float32 = -0.33
fmt.Println(p1)
var p2 float64 = -79787878.9
fmt.Println(p2)
}
99.99
-0.33
-7.97878789e+07
4.3 float64 比float32准确
小数部分可能丢失,造成精度损失,要保存高精度的数应该选择float64
Go语言的浮点型默认是float64类型
package main
import "fmt"
func main(){
var p1 float32 = 897.0000023
var p2 float64 = 897.0000023
fmt.Println("p1 = ",p1)
fmt.Println("p2 = ",p2)
p3 := -12.90
// GO语言默认是使用float64类型
fmt.Printf("p3 type = %T",p3)
}
p1 = 897
p2 = 897.0000023
p3 type = float64
4.4 浮点是强制转换
需要说明float32 和 float64 是两种类型,不能直接相互赋值
package main
import "fmt"
var f1 float32
var f2 float64
func main() {
f2 = 1212.09
fmt.Printf("f2 type is %T, value is %v\n",f2,f2)
// 运行报错
//cannot use f2 (type float64) as type float32 in assignment
f1 = f2
fmt.Printf("f1 type is %T, value is %v\n",f1,f1)
}
我们看看浮点数float32 和 float64类型怎么转换
package main
import "fmt"
var f1 float32
var f2 float64
func main() {
f2 = 1212.09
fmt.Printf("f2 type is %T, value is %v\n",f2,f2)
// 强制转换成float32类型
f1 = float32(f2)
fmt.Printf("f1 type is %T, value is %v\n",f1,f1)
}
f2 type is float64, value is 1212.09
f1 type is float32, value is 1212.09
5. 字符类型
Go语言中支持两种字符类型 分别是byte 和 rune
byte型 ,实际上是uint8类型的别称,代表了ASCII码的一个字符
rune 类型,代表一个unicode 字符 ,实际是一个int32类型,在处理中文,日文或者其他符合类型时需要用到,Go语言中使用特殊的rune类型来处理Unicode,让基于Unicode的文本处理更为方便
package main import "fmt" func main() { var a byte = 'a' var b rune = '中' // a的值`a`对应的ASCII编码是97 实际类型是uint8 fmt.Printf("a value = %d type = %T\n", a, a) // b的值`中`对应的Unicode码是20013 实际类型是int32 fmt.Printf("b value = %d type = %T\n", b, b) // 输出对应的字符 fmt.Printf("a = %c b = %c",a,b) }
a value = 97 type = uint8 b value = 20013 type = int32 a = a b = 中
Unicode 是字符集,ASCII 也是一种字符集,UTF-8是一种编码规则
字符集为每一个字符分配一个唯一的ID,我们使用的所有字符在unicode字符集中都有唯一的ID对应.
utf-8 是编码规则,将unicode字符集中的ID以某种形式进行编码
在Go语言中,字符的本质是一个数字,格式化输出时%c,会输出该数字对应的unicode字符
package main import "fmt" func main(){ var v1 int8 = 102 fmt.Printf("v1 = %c\n",v1) var v2 int = 22381 fmt.Printf("v2 = %c\n",v2) }
v1 = f v2 = 坭
字符串是可以进行运算的
package main import "fmt" func main() { var v1 int = 10 v1 += 97 fmt.Printf("v1 = %d,unicode = %c",v1,v1) }
v1 = 107,unicode = k
6. string类型
Go语言字符串数据对应的字节数组,字符串的只读属性禁止了在程序中对底层字节数组的元素修改,字符串赋值只是赋值了数据地址和对应长度,而不会底层数据的赋值
字符串是一串固定长度的字符连接起来的字符序列,Go语言的字符串的字节使用utf-8编码标识的unicode文本
字符串类型也就是string类型定义很简单
package main
import "fmt"
var s1 string
func main() {
s1 = "Celtic 凯尔特人"
s2 := "Lakers 湖人"
var s3 string = "Rocket 火箭"
fmt.Printf("s1 = %s type = %T\n",s1,s1)
fmt.Printf("s2 = %s type = %T\n",s2,s2)
fmt.Printf("s3 = %s type = %T\n",s3,s3)
}
s1 = Celtic 凯尔特人 type = string
s2 = Lakers 湖人 type = string
s3 = Rocket 火箭 type = string
字符串的内容可以用类似数组下标的方式获取,但是与数组不同的是,字符串的内容不能在初始化之后修改
package main
import "fmt"
func main() {
var s1 string = "hello world ~~"
// 使用内置函数len()获取字符串长度
l := len(s1)
fmt.Printf("s1 的长度是 : %d\n",l)
// 获取第一个字符
ch1 := s1[8]
fmt.Printf("%c ch1 = %v,type = %T\n",ch1,ch1,ch1)
}
s1 的长度是 : 14
r ch1 = 114,type = uint8
看一个错误的例子
package main
import "fmt"
func main() {
var s1 string = "hello world ~~"
//会报编译错误
s1[0] = "H"
fmt.Println(s1[0])
}
cannot assign to s1[0]
字符串的两种表示形式
- 双引号 ,字符串的值在书写在双引号中是最常见的表达方式,也称为字符串字面量,这种形式不能跨行,如果字符串太长,可以使用 + 拼接
- 反引号, 以字符串原生样式输出,包括换行和特殊字符
package main
import "fmt"
func main() {
s0 := "hello" +
"world"
s0 += "\n 中国"
fmt.Println(s0)
}
helloworld
中国
package main
import "fmt"
func main() {
// 定义多行字符串
var s1 string = `怒发冲冠
凭栏处潇潇雨歇
抬望眼
仰天长啸`
fmt.Println(s1)
}
怒发冲冠
凭栏处潇潇雨歇
抬望眼
仰天长啸
以字节数组方式遍历数组
package main
import "fmt"
func main(){
var s1 string = "golang 中国"
// 因为字符占1个字节,汉字占3个字节 所以参数s1的长度是13
l := len(s1)
for i:= 0 ;i<l;i++{
ch := s1[i] // 依据下标取字符串中的字符,类型为byte
fmt.Printf("%T,%d,%d\n",ch,i,ch)
}
}
uint8,0,103
uint8,1,111
uint8,2,108
uint8,3,97
uint8,4,110
uint8,5,103
uint8,6,32
uint8,7,228
uint8,8,184
uint8,9,173
uint8,10,229
uint8,11,155
uint8,12,189
以unicode字符遍历数组
package main
import "fmt"
func main(){
var s1 string = "golang 中国"
for i,v := range s1{
// v是rune类型
fmt.Printf("%d,%T,%d,%c\n",i,v,v,v)
}
}
0,int32,103,g
1,int32,111,o
2,int32,108,l
3,int32,97,a
4,int32,110,n
5,int32,103,g
6,int32,32,
7,int32,20013,中
10,int32,22269,国
6.1 补充1:基本数据类型转换
Go语言中不同类型变量之间相互赋值时需要显式转换(不能自动转换)
转换的表达式 T(v) , 意思是将v转换成T类型
多见于整数的不同类型之间的转换,或者不同浮点数类型之间的转换,或是整数与浮点数之间的相互转
package main
import "fmt"
func main() {
var v1 int8 = 99
var v2 int
fmt.Printf("v1 type is %T,value is %d\n",v1,v1)
fmt.Printf("v2 type is %T,value is %d\n",v2,v2)
v2 = int(v1)
fmt.Printf("v2 type is %T,value is %d\n",v2,v2)
}
v1 type is int8,value is 99
v2 type is int,value is 0
v2 type is int,value is 99
GO语言中数据类型的值范围可以从大向小转换,也可以从小向大转换
package main
import "fmt"
func main() {
// int8 的范围是 -128 ~ 127
var v1 int8
var v2 int64 = 9999999
var v3 float64
// 不会报错, 结果是按溢出处理
v1 = int8(v2)
v3 = float64(v2)
fmt.Printf("%T, %d\n",v1,v1)
fmt.Printf("%T, %f\n",v3,v3)
}
int8, 127
float64, 9999999.000000
6.2 补充2 基本数据类型和string 类型的转换
在实际应用中,string 类型和基础类型的相互转换非常常见
例如,整数类和浮点数类型,bool型等与string类型之间的转换
基础类型转成string类型
方法1: 通过包 fmt 包的Sprintf()函数去实现
package main
import "fmt"
func main(){
var v1 int64 = 99998767
var f float64 = 90.7978
var b bool = true
var ch byte = 'w'
var s string
s = fmt.Sprintf("%d",v1)
fmt.Printf("v2 = %s, %T\n",s,s)
s = fmt.Sprintf("%f",f)
fmt.Printf("v2 = %s, %T\n",s,s)
s = fmt.Sprintf("%t",b)
fmt.Printf("v2 = %s, %T\n",s,s)
s = fmt.Sprintf("%c",ch)
fmt.Printf("v2 = %s, %T\n",s,s)
}
v2 = 99998767, string
v2 = 90.797800, string
v2 = true, string
v2 = w, string
基础数据类型转换成string类型
方法2 : 使用 strconv 包中的函数实现
package main
import (
"fmt"
"strconv"
)
func main() {
var n int8 = 12
var f float64 = 23.001
var b bool = false
// FormatInt函数中传入的第一个参数应该是int64类型
s := strconv.FormatInt(int64(n),10)
fmt.Printf("s = %s and type = %T\n",s,s)
// 其中的参数说明参考文档
s = strconv.FormatFloat(f,'f',10,64)
fmt.Printf("s = %s and type = %T\n",s,s)
s = strconv.FormatBool(b)
fmt.Printf("s = %s and type = %T\n",s,s)
}
s = 12 and type = string
s = 23.0010000000 and type = string
s = false and type = string
strconv 包中有其他的方法可以将string类型转换成整数类型,浮点数类型,bool类型,函数名为 ParseInt() ParseBool() ParseFloat() **ParseUint()
package main
import (
"fmt"
"strconv"
)
func main() {
var s1 string = "99090"
var s2 string = "12.090"
var s3 string = "true"
var s4 string = "97"
var s5 string = "helloworld"
n, _ := strconv.ParseInt(s1, 10, 64)
fmt.Printf("n = %d,type = %T\n", n, n)
f, _ := strconv.ParseFloat(s2, 64)
fmt.Printf("f = %f,type = %T\n", f, f)
b, _ := strconv.ParseBool(s3)
fmt.Printf("b = %t,type = %T\n", b, b)
n2, _ := strconv.ParseUint(s4, 10, 64)
fmt.Printf("n2 = %d,type = %T\n", n2, n2)
// 错误原因是s5的有效数据不能转换成指定的类型
n3, err := strconv.ParseInt(s5, 10, 64)
if err !=nil{
fmt.Println("error = ",err)
}else{
fmt.Printf("n = %d,type = %T\n", n3, n3)
}
}
n = 99090,type = int64
f = 12.090000,type = float64
b = true,type = bool
n2 = 97,type = uint64
error = strconv.ParseInt: parsing "helloworld": invalid syntax
7. 补充3 Go语言中常见转义符
转义符 | 含义 |
---|---|
\r | 回车符(返回行首) |
\n | 换行符 |
\t | 制表符 |
\' | 单引号 |
\" | 双引号 |
\\ | 反斜杠 |
package main
import "fmt"
func main() {
var s1 string = "\"D:\\Go\\bin\\go.exe\""
fmt.Println(s1)
}
"D:\Go\bin\go.exe"