基本两种

  1. 基本类型(4个):数据类型 - 图1

    1. 布尔bool
    2. 数字类型
      1. 整型 1. int与uint 2. 显性的整型 3. 字符类型byte(类似uint8)/rune(类似int32);注意(字符串为string类型,不属于整型)
      2. 浮点数
      3. uintptr
    3. 字符串
  2. 复合数据类型

    1. 值类型:
      1. 数组:一维数组类型[len]type比如[3]int,实际数据
      2. 结构体
    2. 引用类型:指针、切片、集合、channel
    3. 函数
类型 实际数据长什么样子?
值类型 数组 一维数组类型[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. 两大类 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包来查询。(注意,查出来的是字节数)
  1. package main
  2. import (
  3. "fmt"
  4. "unsafe"
  5. )
  6. func main() {
  7. fmt.Printf("Size of int on this platform is %d bytes.\n", unsafe.Sizeof(int(0)))
  8. }
  9. /*
  10. 上述代码中,使用了不安全.Sizeof()函数来获取int类型在当前平台上所占用的字节数。
  11. 运行代码后,输出的信息将显示int类型的大小。
  12. 请注意,使用unsafe包可能会破坏Go语言的内存安全性,因此必须谨慎使用。
  13. */

! byte/ rune(常用于字符)

后面会涉及,字符串转化成元素为字符的切片,进行处理,会用到转换

  1. 什么是字符?
    数据类型 - 图3
  2. 字符 vs 字符串
字符 字符串
语法 单引号 双引号
组成 字符,往往只有一字符 转义字符除外 字符串有一个或多个字符构成,且都隐藏了一个结束符'\0'
类型 byte / rune
go里是没有char类型的
string
打印 %c
note: %U 打印Unicode字符 %#U 打印带字符的Unicode
%s
  1. 字符有两种类型,byte vs rune
    1. 本质
    • 1个字节:标准的英文字母、数字、基本符号(ASCII范围内的字符)。
    • 2个字节:部分拉丁扩展字符、其他语言的字符(如西里尔字母、希腊字母等)。
    • 3个字节大部分中日韩文字和一些特殊符号。
    • 4个字节:罕见的Unicode字符及大部分表情符号(Emoji)。(有的中文字占4byte)
    1. 应用:
byte rune
表示范围 ASCII范围内的字符 ASCII范围外的字符
本质 uint8 int32
什么时候遇得到? 1. 按x[i]来遍历字符串x 数据类型 - 图4
2. 声明变量 var a byte = 'A'
3. 修改含有英文字符串(上方code) 数据类型 - 图5
1. 使用语法糖:=,比如 a := 'm', b := '好' 无论是英文字符还是中文,都推断为rune
2. <font style="color:rgb(36, 41, 46);">for k, v := range s_1</font>中获得的 v是rune 数据类型 - 图6
3. 修改含有中文的字符串(下方code) 数据类型 - 图7
倾向 一般倾向于使用byte,比较节省空间 比较少用
  1. 底层原理
  1. // 遍历字符串
  2. func traversalString() {
  3. s := "pprof.cn博客"
  4. //byte
  5. for i := 0; i < len(s); i++ {
  6. fmt.Printf("%v(%c) ", s[i], s[i])
  7. }
  8. fmt.Println()
  9. //rune
  10. for _, r := range s {
  11. fmt.Printf("%v(%c) ", r, r)
  12. }
  13. fmt.Println()
  14. }

数据类型 - 图8

分析:

因为UTF8编码下一个中文汉字由3~4个字节组成,所以我们不能简单的按照字节去遍历一个包含中文的字符串,否则就会出现上面输出中第一行的结果。 字符串底层是一个byte数组,所以可以和[]byte类型相互转换。字符串是不能修改的, 字符串是由byte字节组成,所以字符串的长度是byte字节的长度。 rune类型用来表示utf8字符,一个rune字符由一个或多个byte组成。

(new)byte 类型变量可以存什么?

在 Go 语言中,byte 类型是 uint8 的别名,表示一个 8 位无符号整数。它的取值范围是 0255,因此它可以表示一个字节的内容。byte 类型的变量通常用于处理原始的字节数据,尤其在操作二进制数据、文件、网络通信等场景时非常常见。

**<font style="color:#ED740C;">byte</font>** 可以存储的内容:

1、字符(字符的字节表示):

  1. - Go 中,`byte` 类型通常用来表示字符的 ASCII UTF-8 编码值。例如,字符 `'a'` ASCII 编码中的值是 `97`,你可以使用 `byte` 类型来存储这个值:
  1. var b byte = 'a' // b 的值是 97,表示字符 'a'
  1. - 因为 Go 中的字符常量(如 `'a'`)实际是对应字符的 Unicode 码点(对于 ASCII 字符集来说是相同的),所以 `byte` 存储的实际上是字符对应的字节值。

2、字节数据:

  1. - `byte` 类型也可以用于存储二进制数据。例如,`[]byte` 类型就是字节切片,常用于表示一组字节:
  1. var data []byte = []byte{72, 101, 108, 108, 111} // 表示 "Hello" 的字节序列

**<font style="color:#ED740C;">byte</font>** 的使用示例:

  1. package main
  2. import "fmt"
  3. func main() {
  4. // 字符 'a' 的 ASCII 值是 97
  5. var b byte = 'a'
  6. fmt.Println(b) // 输出: 97
  7. // 'b' 和 'c' 的 ASCII 值分别是 98 和 99
  8. var byteSlice []byte = []byte{'b', 'c'}
  9. fmt.Println(byteSlice) // 输出: [98 99]
  10. // 通过字节切片表示字符串
  11. str := string([]byte{72, 101, 108, 108, 111})
  12. fmt.Println(str) // 输出: "Hello"
  13. //byteStr := []byte{'H', 'e', 'l', 'l', 'o'}
  14. }

总结:

  • 字符byte 可以存储字符的字节值,通常是 ASCII 字符的编码或 UTF-8 字符集中的字节。
  • 二进制数据byte 也可以存储任何字节数据(例如文件内容、网络数据等)。

因此,byte 主要用于存储 8 位无符号整数,尤其是在表示字符或处理原始字节数据时非常有用。

?uintptr

浮点型

数据类型 - 图9

复数

数据类型 - 图10

3.字符串

字符串的值为双引号(“)中的内容,使用UTF—8编码

3.1 字符串转义字符

数据类型 - 图11

3.2 多行字符

Go语言中要定义一个多行字符串时,就必须使用反引号字符:
  1. s1 := `第一行
  2. 第二行
  3. 第三行
  4. `
  5. fmt.Println(s1)

转义字符无效:
**
反引号间换行将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出。**

3.3 字符串的常用操作

数据类型 - 图12

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>。无论哪种转换,都会重新分配内存,并复制字节数组。
  1. func changeString() {
  2. s1 := "hello"
  3. // 强制类型转换
  4. byteS1 := []byte(s1)
  5. byteS1[0] = 'H'
  6. fmt.Println(string(byteS1))
  7. s2 := "博客"
  8. runeS2 := []rune(s2)
  9. runeS2[0] = '狗'
  10. fmt.Println(string(runeS2))
  11. }

3.6 字符串长度

string 的长度很特殊: (新门第一坑) • 字节长度:和编码无关,用 len(str)获取的是字节数 • 字符数量:和编码有关,用编码库来计算,如下图(不能使用len(str)/3,因为utf-8也有扩展符)数据类型 - 图13
Tip:如果你觉得字符串里边会出现非 ASC II 的字符,就记得用 utf8 库来计算“长度”

3.6与c语言的差别

  1. FishC”(字符用单引号,字符串用双引号,多个字符穿起来,以 ‘\0’ 结束=字符串,python中单双引号共同相同,内嵌的时候会要求不一样而已)
  2. 多行字符串
    比如下这三种形式所显示的字符串是相同的
    数据类型 - 图14
  3. go语言有自己独自的常用操作
  4. c语言字符的处理,当遇到非英文类的字符串时候,不需要额外类型(go就需要rune)
  5. c语言不可修改字符串,go语言也不可以修改,但是可以通过类型转换成rune或者byte类型的切片,修改,再转换成string
  6. 字符串的长度计算也不一样

复合数据类型

值类型:数组,结构

引用类型:指针、切片、集合、channel

零值问题

  • 类型

    类型转换

  1. go不允许隐式类型转换,只能显示类型转换

NOTE:强制类型转换与隐式类型转换(以下为c语言中

  1. 强制类型转换需要运算符
  2. 隐式类型转换
    1. 即属于一个大类(比如int,float….)下的类型,如,相互赋值的过程中,int32与int的转换,编译器会帮你自动完成
    2. 低类型到高类型的隐式类型转换是安全的,不会发生截断。
      高类型到低类型的隐式类型转换是不安全的,会发生截断产生不正确的结果。

数据类型 - 图15

  1. 3. 什么时候会发生隐式类型转换?
算术运算中,低类型转换为高类型
赋值表达式中,赋值符“=”左边的变量值转换为右边变量的类型
函数调用时,实参转换为形参的类型
函数返回时,函数返回值,ruturn表达式转换为返回值类型

>

  1. 兼容性???
    要注意的是什么类型能转换——兼容类型——int('G')
    什么类型不能转换,原来啥样就啥样——不兼容类型——bool

类型定义

type MyInt **<font style="color:rgb(51, 51, 51);">int</font>**_<font style="color:rgb(153, 153, 136);">//将MyInt定义为int类型</font>_其实就是起小名

实例
  1. 结构体
    数据类型 - 图16
  2. 同时定义多个类型
    数据类型 - 图17

类型别名

  1. 语法结构:<font style="color:rgb(0, 134, 179);">type</font> TypeAlias = Type
    1. 类型别名是Go1.9版本添加的新功能。
    2. 类型别名规定:TypeAlias只是Type的别名,本质上TypeAlias与Type是同一个类型。就像一个孩子小时候有小名、乳名,上学后用学名,英语老师又会给他起英文名,但这些名字都指的是他本人。
  2. 实例:
    我们之前见过的rune和byte就是类型别名,他们的定义如下:
    <font style="color:rgb(0, 134, 179);">type</font> byte = uint8
    <font style="color:rgb(0, 134, 179);">type</font> rune = int32

?类型定义和类型别名的区别

  1. //类型定义
  2. type NewInt int
  3. //类型别名
  4. type MyInt = int
  5. func main() {
  6. var a NewInt
  7. var b MyInt
  8. fmt.Printf("type of a:%T\n", a) //type of a:main.NewInt
  9. fmt.Printf("type of b:%T\n", b) //type of b:int
  10. }
结果显示a的类型是main.NewInt,表示main包下定义的NewInt类型。b的类型是int。MyInt类型只会在代码中存在,编译完成时并不会有MyInt类型。(编译完成后还要打代码?给我感觉:类型定义>类型别名)

数据类型上与其他语言差异

类型转换

Go语言中只有强制类型转换,没有隐式类型转换。该语法只能在两个类型之间支持相互转换的时候使用。
  1. 不支持隐式类型转换——证明
    1. GO语言完全不支持隐式类型转换
      数据类型 - 图18
    2. 严格到,别名和原有类型也不能进行隐式类型转换
      数据类型 - 图19
  2. 支持——强制类型转换
    1. 语法: T(表达式) 其中,T表示要转换的类型。表达式包括变量、复杂算子和函数返回值等.
    2. 比如
      var a int64 = 10;
      var b int32
      b = int32(a)

预定义值

  1. 预定义值,可用系统自带的
    数据类型 - 图20
    (比如,这是go语言自带的,在该类型下的最大值)
  2. 支持垃圾回收机制(目前不知道是啥

支持指针访问,不支持指针运算

数据类型 - 图21
c语言会利用指针的运算,来进行对连续内存的访问,但go里面是不行的

空字符串

string在别的语言中通常无初始化为nil,但是在golang中,首先string是值类型,其次是初始化为空字符串“”而不是空(什么是空???
数据类型 - 图22

其实除此之外,其实go大多变量若未初始化,会默认为nil

c语言需要初始化未NULL,而非默认

布尔类型

不支持类型转换