golang:数组的传递(引用传递、指针传递、值传递)

谁践踏了优雅 2022-11-25 04:14 298阅读 0赞

概念介绍

数组与切片

  • 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列。数组长度最大为2Gb,它是值类型。
  • 切片是对数组一个连续片段的引用,所以切片是一个引用类型。

按值传递和按引用传递

Go语言中函数的参数有两种传递方式,按值传递和按引用传递。

  • Go默认使用按值传递来传递参数,也就是传递参数的副本。在函数中对副本的值进行更改操作时,不会影响到原来的变量。

  • 按引用传递其实也可以称作”按值传递”,只不过该副本是一个地址的拷贝,通过它可以修改这个值所指向的地址上的值。

golang中,在函数调用时,引用类型(slice、map、interface、channel)都默认使用引用传递。

数组传递时的缺点

一般情况下,传递指针的消耗比传递副本的少,尤其是当数组特别大时。具体原因是:

  • 值传递需要完整的复制初始数组并将这份拷贝放到栈中,这将耗费大量运行时间,因而值传递方式的效率比较低。
  • 初始数组的拷贝需要占用额外的内存空间(栈中的内存)
  • 编译程序需要专门产生一部分用来复制初始数组的代码,这将使程序变大。

如何避免

如上面介绍的,有两种方法,第一种利用指针,即引用传递;第二种使用切片,因为切片是引用类型,默认会使用引用传递。

  1. func main() {
  2. var arr = [5]int{
  3. 1, 2, 3, 4, 5}
  4. mod(arr[:]) //[0 1 2 3 4] ---- 使用切片进行传递: 因为切片是引用类型,默认会使用引用传递。
  5. fmt.Println(arr)
  6. arr = [5]int{
  7. 1, 2, 3, 4, 5}
  8. mod2(arr) //[1 2 3 4 5]
  9. fmt.Println(arr) //------传递副本
  10. arr = [5]int{
  11. 1, 2, 3, 4, 5}
  12. mod3(&arr)
  13. fmt.Println(arr) //[0 1 2 3 4] 利用指针
  14. var p *[]int
  15. var brr = []int{
  16. 1, 2, 3, 4, 5}
  17. p = &brr
  18. mod4(p)
  19. fmt.Println(brr) //[0 1 2 3 4]
  20. }
  21. func mod(arr []int) {
  22. for i := 0; i < len(arr); i++ {
  23. arr[i] = i
  24. }
  25. }
  26. func mod2(arr [5]int) {
  27. for i := 0; i < len(arr); i++ {
  28. arr[i] = i
  29. }
  30. }
  31. func mod3(arr *[5]int) {
  32. for i := 0; i < len(arr); i++ {
  33. arr[i] = i
  34. }
  35. }
  36. func mod4(arr *[]int) {
  37. for i := 0; i < len(*arr); i++ {
  38. (*arr)[i] = i
  39. }
  40. }

易错点【append】

  1. func main() {
  2. var arr = []int{
  3. 1, 2, 3, 4, 5}
  4. mod(arr[:]) //[1 2 3 4 5] 在对slice进行append操作的时候,返回的是新的引用,并非原始引用
  5. fmt.Println(arr)
  6. arr = []int{
  7. 1, 2, 3, 4, 5}
  8. mod4(&arr) //[1 2 3 4 5 6]
  9. fmt.Println(arr)
  10. }
  11. func mod(arr []int) {
  12. arr = append(arr, 6)
  13. }
  14. func mod4(arr *[]int) {
  15. (*arr) = append((*arr), 6)
  16. }

发表评论

表情:
评论列表 (有 0 条评论,298人围观)

还没有评论,来说两句吧...

相关阅读

    相关 传递引用传递指针传递

    一、值传递 1、特点: (1)形参是实参的拷贝,改变形参的值并不会影响外部实参的值。 (2)从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,不能

    相关 传递,地址传递引用传递

    什么是值传递,地址传递和引用传递?它们有什么不同?这在学校考试,找工作面试中都是常见的问题。它们之间的区别容易搞错,长时间不用也容易忘记。最近又被问到这个问题,想想还是整理一下