总
基本两种
基本类型(4个):
- 布尔bool
- 数字类型
- 整型 1. int与uint 2. 显性的整型 3. 字符类型byte(类似uint8)/rune(类似int32);注意(字符串为string类型,不属于整型)
- 浮点数
- uintptr
- 字符串
复合数据类型
- 值类型:
- 数组:一维数组类型
[len]type
比如[3]int
,实际数据 - 结构体
- 数组:一维数组类型
- 引用类型:指针、切片、集合、channel
- 函数
- 值类型:
类型 | 实际数据长什么样子? | ||
---|---|---|---|
值类型 | 数组 | 一维数组类型[len]type 比如[3]int |
[3]int{1, 2, 3} 或者[...]int{1, 2, 3} |
二维数组类型比如[3][2]int |
[3][2]int{{1,2}, {3,4}, {5,6}} 或者[...][2]int{{1,2}, {3,4}, {5,6} } |
||
结构体 | |||
引用类型 | 指针 | ||
切片 | |||
集合map | |||
channel |
:::info NOTE:对比一下c语言的数据类型
:::
基本数据类型
1.布尔值
Go语言中以bool类型进行声明布尔型数据,布尔型数据只有true(真)和false(假)两个值。注意:
- 布尔类型变量的默认值为false。
- Go 语言中不允许将整型强制转换为布尔型.
- 布尔型无法参与数值运算,也无法与其他类型进行转换。
2.数字类型
整型
显性整型
这非常表现go语言的特性之一——显性
- 两大类
1. 有符号:int8、int16、int32、int64
2. 无符号:uint8、uint16、uint32、uint64
其中,uint8就是我们熟知的byte型,int16对应C语言中的short型,int64对应C语言中的long型。
int与uint
int与uint的长度,与操作系统、处理器架构、编译器相关,一般是32位或者64位(=4字节或者8字节),可以使用Go语言内置的unsafe包来查询。(注意,查出来的是字节数)
package main
import (
"fmt"
"unsafe"
)
func main() {
fmt.Printf("Size of int on this platform is %d bytes.\n", unsafe.Sizeof(int(0)))
}
/*
上述代码中,使用了不安全.Sizeof()函数来获取int类型在当前平台上所占用的字节数。
运行代码后,输出的信息将显示int类型的大小。
请注意,使用unsafe包可能会破坏Go语言的内存安全性,因此必须谨慎使用。
*/
! byte/ rune(常用于字符)
后面会涉及,字符串转化成元素为字符的切片,进行处理,会用到转换
- 什么是字符?
- 字符 vs 字符串
字符 | 字符串 | |
---|---|---|
语法 | 单引号 | 双引号 |
组成 | 字符,往往只有一字符 转义字符除外 | 字符串有一个或多个字符构成,且都隐藏了一个结束符'\0' |
类型 | byte / rune go里是没有char类型的 |
string |
打印 | %c note: %U 打印Unicode字符 %#U 打印带字符的Unicode |
%s |
- 字符有两种类型,byte vs rune
- 本质
- 1个字节:标准的英文字母、数字、基本符号(ASCII范围内的字符)。
- 2个字节:部分拉丁扩展字符、其他语言的字符(如西里尔字母、希腊字母等)。
- 3个字节:大部分中日韩文字和一些特殊符号。
- 4个字节:罕见的Unicode字符及大部分表情符号(Emoji)。(有的中文字占4byte)
- 应用:
byte | rune | |
---|---|---|
表示范围 | ASCII范围内的字符 | ASCII范围外的字符 |
本质 | uint8 | int32 |
什么时候遇得到? | 1. 按x[i]来遍历字符串x 2. 声明变量 var a byte = 'A' 3. 修改含有英文字符串(上方code) |
1. 使用语法糖:= ,比如 a := 'm', b := '好' 无论是英文字符还是中文,都推断为rune2. <font style="color:rgb(36, 41, 46);">for k, v := range s_1</font> 中获得的 v是rune 3. 修改含有中文的字符串(下方code) |
倾向 | 一般倾向于使用byte,比较节省空间 | 比较少用 |
- 底层原理
// 遍历字符串
func traversalString() {
s := "pprof.cn博客"
//byte
for i := 0; i < len(s); i++ {
fmt.Printf("%v(%c) ", s[i], s[i])
}
fmt.Println()
//rune
for _, r := range s {
fmt.Printf("%v(%c) ", r, r)
}
fmt.Println()
}
分析:
因为UTF8编码下一个中文汉字由3~4个字节组成,所以我们不能简单的按照字节去遍历一个包含中文的字符串,否则就会出现上面输出中第一行的结果。 字符串底层是一个byte数组,所以可以和[]byte类型相互转换。字符串是不能修改的, 字符串是由byte字节组成,所以字符串的长度是byte字节的长度。 rune类型用来表示utf8字符,一个rune字符由一个或多个byte组成。(new)byte 类型变量可以存什么?
在 Go 语言中,byte
类型是 uint8
的别名,表示一个 8 位无符号整数。它的取值范围是 0
到 255
,因此它可以表示一个字节的内容。byte
类型的变量通常用于处理原始的字节数据,尤其在操作二进制数据、文件、网络通信等场景时非常常见。
**<font style="color:#ED740C;">byte</font>**
可以存储的内容:
1、字符(字符的字节表示):
- 在 Go 中,`byte` 类型通常用来表示字符的 ASCII 或 UTF-8 编码值。例如,字符 `'a'` 在 ASCII 编码中的值是 `97`,你可以使用 `byte` 类型来存储这个值:
var b byte = 'a' // b 的值是 97,表示字符 'a'
- 因为 Go 中的字符常量(如 `'a'`)实际是对应字符的 Unicode 码点(对于 ASCII 字符集来说是相同的),所以 `byte` 存储的实际上是字符对应的字节值。
2、字节数据:
- `byte` 类型也可以用于存储二进制数据。例如,`[]byte` 类型就是字节切片,常用于表示一组字节:
var data []byte = []byte{72, 101, 108, 108, 111} // 表示 "Hello" 的字节序列
**<font style="color:#ED740C;">byte</font>**
的使用示例:
package main
import "fmt"
func main() {
// 字符 'a' 的 ASCII 值是 97
var b byte = 'a'
fmt.Println(b) // 输出: 97
// 'b' 和 'c' 的 ASCII 值分别是 98 和 99
var byteSlice []byte = []byte{'b', 'c'}
fmt.Println(byteSlice) // 输出: [98 99]
// 通过字节切片表示字符串
str := string([]byte{72, 101, 108, 108, 111})
fmt.Println(str) // 输出: "Hello"
//byteStr := []byte{'H', 'e', 'l', 'l', 'o'}
}
总结:
- 字符:
byte
可以存储字符的字节值,通常是 ASCII 字符的编码或 UTF-8 字符集中的字节。 - 二进制数据:
byte
也可以存储任何字节数据(例如文件内容、网络数据等)。
因此,byte
主要用于存储 8 位无符号整数,尤其是在表示字符或处理原始字节数据时非常有用。
?uintptr
浮点型
复数
3.字符串
字符串的值为双引号(“)中的内容,使用UTF—8编码3.1 字符串转义字符
3.2 多行字符
Go语言中要定义一个多行字符串时,就必须使用反引号字符:
s1 := `第一行
第二行
第三行
`
fmt.Println(s1)
转义字符无效:
**反引号间换行将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出。**
3.3 字符串的常用操作
3.5 修改字符串
字符串不可修改,要改,需要先将其转换成<font style="color:rgb(199, 37, 78);background-color:rgb(246, 246, 246);">[]rune或[]byte</font>
(切片),完成后再转换为<font style="color:rgb(199, 37, 78);background-color:rgb(246, 246, 246);">string</font>
。无论哪种转换,都会重新分配内存,并复制字节数组。
func changeString() {
s1 := "hello"
// 强制类型转换
byteS1 := []byte(s1)
byteS1[0] = 'H'
fmt.Println(string(byteS1))
s2 := "博客"
runeS2 := []rune(s2)
runeS2[0] = '狗'
fmt.Println(string(runeS2))
}
3.6 字符串长度
string 的长度很特殊: (新门第一坑) • 字节长度:和编码无关,用 len(str)获取的是字节数 • 字符数量:和编码有关,用编码库来计算,如下图(不能使用len(str)/3,因为utf-8也有扩展符)Tip:如果你觉得字符串里边会出现非 ASC II 的字符,就记得用 utf8 库来计算“长度”
3.6与c语言的差别
- FishC”(字符用单引号,字符串用双引号,多个字符穿起来,以 ‘\0’ 结束=字符串,python中单双引号共同相同,内嵌的时候会要求不一样而已)
- 多行字符串
比如下面这三种形式所显示的字符串是相同的 - go语言有自己独自的常用操作
- c语言字符的处理,当遇到非英文类的字符串时候,不需要额外类型(go就需要rune)
- c语言不可修改字符串,go语言也不可以修改,但是可以通过类型转换成rune或者byte类型的切片,修改,再转换成string
- 字符串的长度计算也不一样
复合数据类型
值类型:数组,结构
引用类型:指针、切片、集合、channel
零值问题
- go不允许隐式类型转换,只能显示类型转换
NOTE:强制类型转换与隐式类型转换(以下为c语言中)
- 强制类型转换需要运算符
- 隐式类型转换
- 即属于一个大类(比如int,float….)下的类型,如,相互赋值的过程中,int32与int的转换,编译器会帮你自动完成
- 低类型到高类型的隐式类型转换是安全的,不会发生截断。
高类型到低类型的隐式类型转换是不安全的,会发生截断产生不正确的结果。
算术运算中,低类型转换为高类型
3. 什么时候会发生隐式类型转换?
赋值表达式中,赋值符“=”左边的变量值转换为右边变量的类型
函数调用时,实参转换为形参的类型
函数返回时,函数返回值,ruturn表达式转换为返回值类型
>
- 兼容性???
要注意的是什么类型能转换——兼容类型——int('G')
什么类型不能转换,原来啥样就啥样——不兼容类型——bool
类型定义
type MyInt **<font style="color:rgb(51, 51, 51);">int</font>**_<font style="color:rgb(153, 153, 136);">//将MyInt定义为int类型</font>_
其实就是起小名
- 结构体
- 同时定义多个类型
类型别名
- 语法结构:
<font style="color:rgb(0, 134, 179);">type</font> TypeAlias = Type
- 类型别名是Go1.9版本添加的新功能。
- 类型别名规定:TypeAlias只是Type的别名,本质上TypeAlias与Type是同一个类型。就像一个孩子小时候有小名、乳名,上学后用学名,英语老师又会给他起英文名,但这些名字都指的是他本人。
- 实例:
我们之前见过的rune和byte就是类型别名,他们的定义如下:<font style="color:rgb(0, 134, 179);">type</font> byte = uint8
<font style="color:rgb(0, 134, 179);">type</font> rune = int32
?类型定义和类型别名的区别
结果显示a的类型是main.NewInt,表示main包下定义的NewInt类型。b的类型是int。MyInt类型只会在代码中存在,编译完成时并不会有MyInt类型。(编译完成后还要打代码?给我感觉:类型定义>类型别名)
//类型定义
type NewInt int
//类型别名
type MyInt = int
func main() {
var a NewInt
var b MyInt
fmt.Printf("type of a:%T\n", a) //type of a:main.NewInt
fmt.Printf("type of b:%T\n", b) //type of b:int
}
数据类型上与其他语言差异
类型转换
Go语言中只有强制类型转换,没有隐式类型转换。该语法只能在两个类型之间支持相互转换的时候使用。- 不支持隐式类型转换——证明
- GO语言完全不支持隐式类型转换
- 严格到,别名和原有类型也不能进行隐式类型转换
- GO语言完全不支持隐式类型转换
- 支持——强制类型转换
- 语法: T(表达式) 其中,T表示要转换的类型。表达式包括变量、复杂算子和函数返回值等.
- 比如
var a int64 = 10;
var b int32
b = int32(a)
预定义值
- 预定义值,可用系统自带的
(比如,这是go语言自带的,在该类型下的最大值) - 支持垃圾回收机制(目前不知道是啥)
支持指针访问,不支持指针运算
c语言会利用指针的运算,来进行对连续内存的访问,但go里面是不行的
空字符串
string在别的语言中通常无初始化为nil,但是在golang中,首先string是值类型,其次是初始化为空字符串“”
而不是空(什么是空???)
其实除此之外,其实go大多变量若未初始化,会默认为nil
c语言需要初始化未NULL,而非默认
布尔类型
不支持类型转换