GO语言入门指南:基础语法和常用特性解析(数据类型) | 青训营

81 阅读5分钟

本文将围绕青训营选题《Go 语言入门指南:基础语法和常用特性解析》内容来进行编写,探讨Go语言中数据类型的区别以及底层实现。由于小编本人的技术不太好,可能讲得有些不对的地方,欢迎读者指正,小编希望能和广大营友一起探讨,共同进步。

为什么要了解数据类型的区别

在我学习Go语言函数的时候总会有一个疑惑,为什么有时候放入的变量可以不需要接受返回值就改变了原有的值,而有的变量又不能通过调用函数而改变呢?因此我搜寻了一些资料,才发明,这一切都和我们所引用参数的类型有关...而这类型也意味着函数调用时的传递方式不同...

1、数据类型之值类型

1.1、什么是值类型

正如前文提到的,在函数调用时,即使在函数里改变了这个值,但是函数结束后,值却没有改变,这种类型就叫值类型。

  • 值类型的变量直接存储其值本身
  • 当将一个值类型的变量赋值给另一个变量或作为函数参数进行传递时,会进行值的拷贝,每个变量都有自己的独立内存空间
  • 对一个变量的修改不会影响到其他变量

这里给出一个简单的示例:

image-20230809171816996.png

也就是函数中的x变量并非main里边x变量,函数中的x只是一个形参,是main中x变量的拷贝,就算改变了也影响不到x本身。

1.2、值类型有哪些

基本数据类型一般都为值类型,其中包括:int、float、bool、string、数组等,其中int、float的初始值为0,bool的初始值为false,string的初始值为“”。

2、数据类型之引用类型

2.1、什么是引用类型

正如前文提到的,在函数调用时,在函数里改变了这个值,函数结束后,值也发生了改变,这种类型就叫引用类型。

  • 引用类型的变量本身并不直接存储实际的数据,而是存储指向数据的内存地址
  • 当将一个引用类型的变量赋值给另一个变量或作为函数参数进行传递时,会进行地址的拷贝,每个变量都指向原来数据的内存地址
  • 发生改变之后所有指向原来数据地址的数据也会发生改变

这里给出一个简单的示例:

image-20230809173520745.png

也就是函数中的s变量和main中s指向相同的地址,s改变的是指向地址中存储的值,main函数的s再次读取也会读出修改之后的值。

2.2、引用类型有哪些

  1. 切片(Slice):切片是对数组的抽象,它提供了一种动态长度的、灵活的方式来访问数组元素。切片是引用类型,存储了一个指向底层数组的指针、长度和容量。
  2. 映射(Map):映射是一种无序的键值对集合。映射使用哈希表实现,存储了一个指向哈希表的指针。
  3. 通道(Channel):通道用于在不同的goroutine之间进行通信和同步。通道允许通过发送和接收操作来传递数据。通道是引用类型,存储了一个指向通道数据结构的指针。
  4. 接口(Interface):接口是一种抽象类型,定义了一组方法的集合。接口变量存储了一个指向实际实现类型的指针和类型信息。

3、如何声明一个值类型/引用类型

值类型直接通过var来声明就好,如:

var num int
var fnum float64
var str string
var flag bool

而引用类型需要通过make来进行声明,在声明是需要给定大小,如:

var slice = make([]string,10)
var mp = make(map[string]string, 100)

值得一提的是,slice切片可以直接通过var slice []string 进行声明,后续通过append进行数据的增加。

4、切片的底层实现

在Go语言中,切牌是数组的底抽象,切片的定义则是定义了一个指针指向了一个创建好的数组内存地址,因此切片的底层实现主要包括了三个部分:指针、长度和容量。其中长度为该切片能存储的数据长度,容量则为底层数组内存地址分配的数量,这两个不是同一个东西。

以 []int 为例,它表示一个整数类型的切片。

  1. 指针(Pointer):切片中的指针指向底层数组的起始位置。通过指针,切片可以访问和修改底层数组中的元素。
  2. 长度(Length):切片的长度表示切片中当前存储的元素个数。通过 len() 函数可以获取切片的长度。
  3. 容量(Capacity):切片的容量表示切片底层数组的可访问元素个数。通过 cap() 函数可以获取切片的容量。

这里给出一个简单例子:

image-20230809175600861.png


个人思考与总结:我认为掌握这些数据类型是十分有必要的,这些东西都可以称之为基础,正所谓“基础不牢,地动山摇”。因此我就想着把这东西总结出来,虽然可能会有些不全面,或者有些过于简单了。但对于我这种Go小白来说是十分重要的,至少会降低函数调用时翻车的概率。。。

至此,数据类型的分析基本结束了,可能有些不完全的,欢迎大家在评论区里补充~