zoukankan      html  css  js  c++  java
  • golang 小知识-持续更新中

    Golang 中的指针 - Pointer

    Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int 及 float 系列,高级类型包含 struct,array/slice,map,chan, func 。
     
    相比 Java,Python,Javascript 等引用类型的语言,Golang 拥有类似C语言的指针这个相对古老的特性。但不同于 C 语言,Golang 的指针是单独的类型,而不是 C 语言中的 int 类型,而且也不能对指针做整数运算。从这一点看,Golang 的指针基本就是一种引用。
     
    那么 Golang 为什么需要指针?这种指针又能有什么独特的用途呢?
     
    在学习引用类型语言的时候,总是要先搞清楚,当给一个函数/方法传参的时候,传进去的是值还是引用。实际上,在大部分引用型语言里,参数为基本类型时,传进去的大都是值,也就是另外复制了一份参数到当前的函数调用栈。参数为高级类型时,传进去的基本都是引用。这个主要是因为虚拟机的内存管理导致的。
     
    内存管理中的内存区域一般包括 heap 和 stack, stack 主要用来存储当前调用栈用到的简单类型数据:string,boolean,int,float 等。这些类型的内存占用小,容易回收,基本上它们的值和指针占用的空间差不多,因此可以直接复制,GC也比较容易做针对性的优化。 复杂的高级类型占用的内存往往相对较大,存储在 heap 中,GC 回收频率相对较低,代价也较大,因此传引用/指针可以避免进行成本较高的复制操作,并且节省内存,提高程序运行效率。
     
    因此,在下列情况可以考虑使用指针:1,需要改变参数的值;2,避免复制操作;3,节省内存;
     
    而在 Golang 中,具体到高级类型 struct,slice,map,也各有不同。实际上,只有 struct 的使用有点复杂,slice,map,chan 都可以直接使用,不用考虑是值还是指针。
     
     
    struct:
     
    对于函数(function),由函数的参数类型指定,传入的参数的类型不对会报错。
    对于方法(method),接收者(receiver)可以是指针,也可以是值,Golang 会在传递参数前自动适配以符合参数的类型。也就是:如果方法的参数是值,那么按照传值的方式 ,方法内部对struct的改动无法作用在外部的变量上。
    方法是包含了接收者的函数。
    函数的格式是固定的,func 函数名 参数 返回值(可选) 函数体。
     
    slice :
     
    slice 实际上相当于对其依附的 array 的引用,它不存储数据,只是对 array 进行描述。因此,修改 slice 中的元素,改变会体现在 array 上,当然也会体现在该 array 的所有 slice 上。
    可以使用 make([]int) 来创建并初始化 map 。
      
    map :
     
    使用 make(map[string]string) 返回的本身是个引用,可以直接用来操作。
    chan :
     
    make(chan int) 返回的是可以直接使用的 channel 。
      
    func :
     
    在 Golang 中,func 可以作为一种值被返回,因此也可以使用类似 Python 的 decorator 的方式来加工函数。
     
    接口指针:
    1. 指针的判断,都涉及到type和value。
    2. 接口指针之间的判等,要基于type与value,一个不同则不等。
    3. 接口指针与其对应实现的结构体指针,可以进行判等操作。

    ------------------------------------------------------------- ------------------------------------------------------------

     数组切片内容复制 copy

    用于将内容从一个数组切片复制到另一个数组切片。如果加入的两个数组切片不一样大,就会按其中较小的那个数组切片的元素个数进行复制。

    slice1 := []int{1, 2, 3, 4, 5} 
    slice2 := []int{5, 4, 3} 
    
    copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中 
    copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置
    

    go 源码中 slice 的数据结构定义

    type slice struct {
        array unsafe.Pointer
        len   int
        cap   int
    }
    

    实际go在append的时候放大cap是有规律的。在 cap 小于1024的情况下是每次扩大到 2 * cap ,当大于1024之后就每次扩大到 1.25 * cap 。

    这个是 slice 的数据结构,它很简单,一个指向真实 array 地址的指针 ptr ,slice 的长度 len 和容量 cap 。


    其中 len 和 cap 就是我们在调用 len(slice) 和 cap(slice) 返回的值。

    slice:用来弥补数组的不足,称之为数组切片

    创建数组切片的方式

    1:基于数组

    var array [10]int = [10]int{1,2,3,4,5,6,7,8,9,10}

    var slice []int = array[:5] //基于数组的前5个元素创建数组切片

    2:直接创建

    slice := make([]int,5,10) //创建一个初始元素个数为5,初始值为0,并预留10个元素的存储                                            空间的数组切片

    内置函数:

    cap():返回数组切片分配的空间大小

    len():返回数组切片当前所存储的元素个数

      

  • 相关阅读:
    初入博客
    winsocket入门学习
    理解音视频 PTS 和 DTS
    理解音视频 PTS 和 DTS
    FFMPEG学习----使用SDL构建音频播放器
    FFmpeg被声明为已否决的解决方案
    FFMPEG结构体分析:AVCodecParameters
    FFMPEG学习----使用SDL播放PCM数据
    如何提取CSDN博客正文内容
    遍历CSDN博客
  • 原文地址:https://www.cnblogs.com/hetonghai/p/9059189.html
Copyright © 2011-2022 走看看