美文网首页
Go 语言学习笔记-指针、切片与结构体

Go 语言学习笔记-指针、切片与结构体

作者: 梁坤同学 | 来源:发表于2020-04-06 22:48 被阅读0次

    指针

    指针就是地址。指针变量就是存储地址的变量

    指针使用

    &p : 引用
    *p : 解引用、间接引用

    栈帧

    用来给函数运行提供内存空间。取内存于 stack 上。

    当函数调用时,产生栈帧。函数调用结束,释放栈帧。

    • 栈帧存储:
      • 局部变量
      • 形参 (形参与局部变量存储地位等同)
      • 内存字段描述值

    指针使用注意

    空指针:未被初始化的指针。

    var p *int
    fmt.Println(*p)  --> err
    

    格式化输出

    %q:以 Go 语言格式显示字符串。默认带有 "" 符
    %v:显示对应数据详细信息

    变量存储

    func swap(x, y *int)  {
        *x, *y = *y, *x
    }
    
    

    等号左边的变量:代表变量所指向的内存空间。(写)
    等号右边的变量:代表变量内存空间存储的数据值。(读)

    指针的函数传参(传引用)

    传地址(引用):将形参的地址值作为函数参数传递。
    传值(数据):将实参的值拷贝一份给形参
    传引用:在 A 栈帧内部,修改 B 栈帧中的变量值

    切片

    为什么用切片

    1. 数组的容量固定,不能自动拓展。
    2. 值传递。数组作为函数参数时,将整个数组值拷贝一份给形参。

    在 Go 语言中,几乎可以在所有的场景中,使用切片替换数组使用。

    切片的本质:

    不是一个数组的指针,是一种数据结构体,用来操作数组内部元素。

    // runtime/slice.go
    type slice struct {
      *p
      len
      cap
    }
    

    切片的使用

    • 数组和切片定义区别:

      • 创建数组时 []指定数组长度
      • 创建切片时,[] 为空,或者 ...
    • 切片名称[low:high:max]

      • low:启示下标位置
      • high:结束下表位置
      • 长度 len:high - low
      • 容量 cap:max-low
    • 截取数组,初始化切片时,没有指定切片容量时,切片容量跟随原数组(切片)

      • s[:high:max]:从 0 开始,到 high 结束。(不包含 high)
      • s[low:]:从 low 开始,到末尾
      • s[:high]:从 0 开始,到 high 结束。容量跟随原先容量。【常用】
    • 切片创建:

      • 自动推导类型创建切片。slice := []int{1, 2, 3}
      • slice := make([]int, 长度, 容量)
      • slice := make([]int, 长度) 创建切片时,没有指定容量,容量==长度
    • 切片做函数参数 --- 传引用(传地址)

    • append:再切片末尾追加元素

      • append(切片对象, 待追加元素)
      • 向切片增加元素时,切片的容量会自动增加。1024 以下时,一两倍方式增加
    • copy 复制切片

      • copy(目标位置切片s1,源切片s2)
      • 拷贝过程中,直接对应位置拷贝
        • 不同类型的切片无法复制
        • 如果s1的长度大于s2的长度,将s2中对应位置上的值替换s1中对应位置的值。如果s1的长度小于s2的长度,多余的将不做替换

    map

    字典、映射,key-value, key:唯一、无需。不能是引用类型数据。

    • 创建方式:

      • var m map[int]string ---不能存储数据
      • m := map[int]string{} ---能存储数据
      • m := make(map[int]string) ---默认 len = 0
      • m := make(map[int]string, 10)
    • 初始化:

      • var m map[int]string = map[int]string{1: "aaa", 2: "bbb"} 保证 key 彼此不重复
      • m := map[int]string{1: "aaa", 2: "bbb"}
    • 赋值:

      • 赋值过程中,如果新 map 元素的 key 与原 map 元素 key 相同 ---> 覆盖(替换)
      • 赋值过程中,如果新 map 元素的 key 与原 map 元素 key 不同 ---> 添加
    • map 的使用

      • 遍历 map
      for key, value := range map {
      
      }
      
      • 判断 map 中 key 是否存在
        • map[下标] 运算:返回两个值,第一个表示 value 的值,如果 value 不存在,则为 nil。第二个表示 key 是否存在的 bool 类型,存在为 true,不存在为 false
        val, has := map[1]
        
    • 删除 map

      • delete()函数:
        • 参数1:待删除元素的 map
        • 参数2:key 值
      • delete(map, key)
        • 删除一个不存在的 key,不会报错
      • map 做函数参数和返回值,传引用

    结构体

    结构体是一种数据类型。类型定义,地位等价于 int、byte、bool、string…,通常放在全局位置。

    type Person struct {
      name string
      sex  byte
      age  int
    }
    

    普通变量定义和初始化

    • 顺序初始化:依次将结构体内部所有成员初始化
      var man Person = Person{"andy", 'm', 20}
      
    • 指定成员初始化:未初始化的成员变量,取该数据类型对应的默认值
      man := Person{name: "andy", age: 20}
      

    普通变量的赋值和使用

    • 使用 . 索引成员变量
      var man Person
      man.name = "nike"
      man.sex = 'm'
      man.age = 99
      

    结构体变量的比较

    • 比较:只能使用 ==!=,不能使用 > < >= <= …
    • 相同结构体类型(成员变量的类型、个数、顺序一致),变量之间可以直接赋值

    结构体地址

    结构体变量的地址 == 结构体首个元素的地址

    结构体传参

    • 将结构体变量的值拷贝一份传递。 ---几乎不用。内存消耗大,效率低。

    • unSafe.Sizeof(变量名) ---查看此种类型的变量所占用的内存空间大小

    指针变量定义和初始化

    • 顺序初始化:依次将结构体内部所有成员初始化

      var man *Person = &Person{"andy", 'm', 20}
      
    • new(Person)

    p := new(Person)
    p.name = "name"
    p.age = 10
    

    指针索引成员变量

    • 使用 . 索引成员变量
      var man Person
      man.name = "nike"
      man.sex = 'm'
      man.age = 99
      

    结构体地址

    结构体指针变量的值 == 结构体首个元素的地址

    结构体指针传参

    • 将结构体变啊零地址值传递(传引用)。---使用频率非常高

    • unSafe.Sizeof(指针):不管何种类型的指针,在 64位操作系统下,大小一致,均为 8 byte

    结构体指针作函数返回值

    • 可以返回局部变量的值

    • 不能返回局部变量的地址 --- 局部变量保存在栈帧上,函数调用结束后,栈帧释放,局部变量的地址,不再受系统保护,随时可能分配给其他程序。

    字符串处理函数

    • 字符串按指定分隔符拆分:Split:

      ret := strings.Split(str, "-")
      
    • 字符串按空格拆分:Fields

      ret = strings.Fields(str)
      
    • 判断字符串结束标记: HasSuffix

      flg := strings.HasSuffix("test.txt", ".aaa")
      
    • 判断字符串起始标识:HasPrefix

      flg := strings.HasPrefix("test.txt", "te.")
      

    相关文章

      网友评论

          本文标题:Go 语言学习笔记-指针、切片与结构体

          本文链接:https://www.haomeiwen.com/subject/ykqwphtx.html