Golang知识点(二)

知识点梳理

  • 结构体可以使用new关键字对结构体进行实例化,得到的是结构体的地址。
    var p2 = new(person)
    p2.name = "小王子"
    p2.age = 28
    p2.city = "上海"
    fmt.Printf("p2=%#v\n", p2) //p2=&main.person{name:"小王子", city:"上海", age:28}
    
  • 结构体可使用&对结构体进行取地址操作相当于对该结构体类型进行了一次new实例化操作。
    p3 := &person{}
    fmt.Printf("%T\n", p3)     //*main.person
    fmt.Printf("p3=%#v\n", p3) //p3=&main.person{name:"", city:"", age:0}
    p3.name = "七米"
    p3.age = 30
    p3.city = "成都"
    fmt.Printf("p3=%#v\n", p3) //p3=&main.person{name:"七米", city:"成都", age:30}
    
  • 没有初始化的结构体,其成员变量都是对应其类型的零值。
    type person struct {
    name string
    city string
    age  int8
    }
    
    func main() {
    var p4 person
    fmt.Printf("p4=%#v\n", p4) //p4=main.person{name:"", city:"", age:0}
    }
    
  • 结构体的方法中值类型的接收者时,Go语言会在代码运行时将接收者的值复制一份。在值类型接收者的方法中可以获取接收者的成员值,但修改操作只是针对副本,无法修改接收者变量本身。
    // SetAge2 设置p的年龄
    // 使用值接收者
    func (p Person) SetAge2(newAge int8) {
    p.age = newAge
    }
    
    func main() {
    p1 := NewPerson("小王子", 25)
    p1.Dream()
    fmt.Println(p1.age) // 25
    p1.SetAge2(30) // (*p1).SetAge2(30)
    fmt.Println(p1.age) // 25
    }
    
  • 结构体占用一块连续的内存。

  • Go语言中支持对结构体指针直接使用.来访问结构体的成员。

  • 在定义一些临时数据结构等场景下还可以使用匿名结构体。

    package main
    
    import (
      "fmt"
    )
    
    func main() {
      var user struct{Name string; Age int}
      user.Name = "小王子"
      user.Age = 18
      fmt.Printf("%#v\n", user)
    }
    
  • runebyte类型就是int32、uint8类型别名
    type byte = uint8
    type rune = int32
    
  • 自定义类型关键字type
    //类型定义
    type NewInt int
    //类型别名
    type MyInt = int
    
  • go 值类型包括 : 所有整型,所有浮点型,bool型,string型,数组struct类型值类型的特点是变量直接存储值,内存通常在 栈(stack) 中分配

  • go 引用类型包括:指针,slice,map,chan,interface引用类型的特点,变量存储的是一个地址,这个地址对应的空间才真正存储的数据,内存分配通常在 堆(heap) 上分配,当没有任何变量引用这个地址的时候,该地址对应的数据空间会被GC回收

  • Go语言提倡面向接口编程。实现接口中的所有方法,就实现了这个接口。

    // 定义接口
    type Mover interface {
    move()
    }
    // Sayer 接口
    type Sayer interface {
    say()
    }
    // 小狗结构体
    type dog struct {}
    // 小狗结构体的移动方法
    func (d dog) move() {
    fmt.Println("狗会动")
    }
    // 实现Sayer接口
    func (d dog) say() {
    fmt.Printf("%s会叫汪汪汪\n", d.name)
    }
    // 调用
    func main() {
      // x 变量接口
    var y Mover
      var x Sayer
    var wangcai = dog{} // 旺财是dog类型
    x = wangcai         // x可以接收dog类型
    var fugui = &dog{}  // 富贵是*dog类型
    x = fugui           // x可以接收*dog类型
    x.say()
      y = wangcai
      y.move()
    }
    
    
  • 切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针、切片的长度(len)和切片的容量(cap)。

  • 要检查切片是否为空,请始终使用len(s) == 0来判断,而不应该使用s == nil来判断。

  • 切片之间是不能比较的,我们不能使用==操作符来判断两个切片是否含有全部相等元素。