引用数据类型

* 本页面主要介绍Go语言引用数据类型的相关内容。

一、值类型

我们刚刚学完了数组(Array)结构体(Struct),也包括之前学到的基本数据类型(int,float,bool和string),它们都属于值类型。值类型的特点就是:变量直接存储值,内存通常在中分配,栈在函数调用完会被释放。

二、引用类型

本节要讨论的,则是引用类型。引用类型的特点是:变量存储的是一个地址,这个地址存储最终的值。内存通常在上分配,通过GC回收。

指针pointer,切片slice,字典map,通道chan,函数function类型等都是引用类型。

另外,关于引用类型和值类型有一个特别重要的不同点

  • 对于引用类型的变量,我们在使用的时候不仅要声明它,还要为它分配内存空间,否则我们的值就没办法存储,进而会触发panic
  • 对于值类型的声明不需要分配内存空间,是因为它们在声明的时候已经默认分配好了内存空间
  func main() {
  var a *int
  *a = 100
  fmt.Println(*a)  //panic

  var b map[string]int
  b["测试"] = 100  //panic
  fmt.Println(b)
}

那么,我们如何分配内存呢?Go语言中有两个内建的函数,用来分配内存:new和make

new函数很少使用。它返回一个类型的指针并初始化为类型零值。

  //内置new函数
  //Type表示类型,new函数只接受一个参数,这个参数是一个类型
  //*Type表示类型指针,new函数返回一个指向该类型内存地址的指针。
  func new(Type) *Type

  //举例
  a := new(int)
  b := new(bool)
  fmt.Printf("%T\n", a) // *int
  fmt.Printf("%T\n", b) // *bool
  fmt.Println(*a)       // 0
  fmt.Println(*b)       // false

make函数只用于slice、map以及chan的内存创建,而且它返回的类型就是这三个类型本身(因为类型本身就是引用类型,就没必要再返回指针)。在使用这三种引用类型时,我们必须用make进行初始化之后才能对它们进行操作。

  //内置make函数
  func make(t Type, size ...IntegerType) Type

  //举例
  var b map[string]int
  b = make(map[string]int, 10)
  b["测试"] = 100
  fmt.Println(b)
三、值传递和引用传递
  • 值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数
  • 引用传递:所谓引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。最早出现c++中

但是,其实在Go语言中不存在引用传递,只有值传递!有很多人误解说,引用类型的是引用传递,误区就是:引用类型在传递到函数内部,可以在函数内部对它的值进行修改而引起的误会。

从传递成本的角度讲,引用类型的值往往要比值类型的值低很多。

能够通过make()函数创建的都是引用类型。

  package main

  import "fmt"

  func updateSlice(s []string) {
      s[0] = "Bye"
  }

  func main() {
      mySlice := []string{"Hi", "There", "how", "are", "you?"}
      updateSlice(mySlice)
      fmt.Println(mySlice)
  }

上面的代码中,运行结果:

[Bye There how are you?]

为什么会是这样呢?通过下面的图解,你一定可以想明白为什么!

为什么会这样?
为什么会这样?
为什么会这样?
为什么会这样?
为什么会这样?
为什么会这样?

没错!因为发生的是值传递!所以,在函数内部发生了一次拷贝操作,但是因为拷贝得到的变量存储的内存地址和传进来的是一样的,也就指向同一个数组,所以改变“影响到了”外面的“变量”。

关于引用类型就总结这么多,接下来,开始学习第一个引用类型吧:切片


* 本页内容参考以下数据源:

  • 《Go程序设计语言》
  • 《Go语言核心36讲》 07 数组和切片
  • https://www.cnblogs.com/qstudy/p/10201106.html
  • https://studygolang.com/articles/27217
  • https://www.jianshu.com/p/18d3bde7d835

* 本页内容更新日志:

  • 2020年11月13日 19:46:18:第一次编辑
  • 2020年11月27日 19:59:23:第二次编辑,增加值类型和引用类型最大区别

凯冰科技 · 代码改变世界,技术改变生活
Next Page→