• Golang


    Golang - 复合类型

     

    Golang - 复合类型

    1. 指针

    • go语言中指针是很容易学习的,比C中容易的多,它可以更简单地执行一些任务
    • 与变量类似,使用前需要声明,使用&符号可以取内存地址
    • 声明指针的格式:
      • var 指针变量名 *指针类型

    指针的使用

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    func main() {
        //声明变量
        var a int = 20
    
        //声明指针变量
        var p *int
        p = &a
    
        //十六进制
        fmt.Printf("a变量的地址是: %x
    ", &a)
        fmt.Printf("p变量存储的指针地址: %x
    ", p)
    
        //使用指针访问值
        fmt.Printf("*p变量的值: %d
    ", *p)
    }
    
    
    //a变量的地址是: c042052080
    //p变量存储的指针地址: c042052080
    //*p变量的值: 20

    通过指针修改变量

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    func main() {
        //定义变量
        var num int = 10
        fmt.Println(&num)
        var ptr *int
    
        //指针赋值
        ptr = &num
        //通过指针修改num
        * ptr = 20
        fmt.Println(num)
    }
    
    //0xc042052080
    //20

    go空指针

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    func main() {
        var ptr *int
        fmt.Println("ptr的值为:", ptr)
    
        //判断空指针
        if ptr == nil{
            fmt.Println("是空")
        }
    }
    
    //ptr的值为: <nil>
    //是空

    值传递和引用传递

    void pass_by_val(int a){
    a++;
    }
    
    void pass_by_ref(int& a){
    a++;
    }
    
    int main() {
    int a = 3;
    
    pass_by_val(a);
    printf("pass_by_val: %d
    ", a)
    printf("pass_by_ref: %d
    ", a)
    }
    
    答案:3,4

    值传递:

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    func swap(a, b int){
        a, b = b, a
    }
    
    func main() {
        a, b := 3, 4
        swap(a, b)
        fmt.Println(a, b)
    }
    
    // 3  4

    go引用传递:

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    func swap(a, b *int){
        *a, *b = *b, *a
    }
    
    func main() {
        a, b := 3, 4
        swap(&a, &b)
        fmt.Println(a, b)
    }
    
    // 4  3

    2. new()和make()

    • new()用来分配内存,但与其他语言中的同名函数不同,它不会初始化内存,只会将内存置零
    • make(T)会返回一个指针,该指针指向新分配的,类型为T的零值,适用于创建结构体
    • make()的目的不同于new(),它只能创建slice、map、channel,并返回类型为T(非指针)的已初始化(非零值)的值

      //package 声明开头表示代码所属包
      package main
      
      import "fmt"
      
      func main() {
          p :=new([]int)
          fmt.Println(p)
      
          //[]int切片
          //10: 初始化10个长度
          //50: 容量为50
          m :=make([]int, 10, 50)
          fmt.Println(m)
      
          m[0] = 10
          (*p)[0] = 10
          fmt.Println(p)
      }

    3. 数组

    声明变量:

    var 数组名[数组长度] 数组类型

    声明和初始化数组:

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    
    func main() {
        //数组长度不让变化
        //定义int类型数组
        var arr1 [5]int
    
        //:=声明并赋值
        arr2 := [3]int{1, 2, 3}
    
        //可以省略大小
        arr3 := [10]int{2, 4, 6, 8, 10}
        fmt.Println(arr1, arr2, arr3)
    
        //定义二维数组
        var grid [4][5]int
        fmt.Println(grid)
    }
    
    //[0 0 0 0 0] [1 2 3] [2 4 6 8 10 0 0 0 0 0]
    //[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]

    数组是值类型还是引用类型?

    package main
    
    import "fmt"
    
    //传入数组,修改元素
    func printArr(arr [5]int)  {
       //修改一个元素
       arr[0] = 100
       for i,v := range arr{
          fmt.Println(i,v)
       }
    }
    
    func main() {
       //定义数组
       var arr1 [5]int
    
    //:=声明并赋值
       arr2 := [3]int{1, 2, 3}
       //可以省略大小
       arr3 := [...]int{2, 4, 6, 8, 10}
       fmt.Println(arr1, arr2, arr3)
    
       //printArr(arr1)
       //报错
       //printArr(arr2)
       printArr(arr3)
    
       //打印原始值
       fmt.Println()
       fmt.Println(arr3)
    }

    4. slice

    • 数组的长度在定义之后无法再次修改,go语言提供了数组切片(slice)来弥补数组的不足
    • 创建切片的各种方式

        //package 声明开头表示代码所属包
        package main
      
        import "fmt"
      
        func main() {
            //声明空切片
            var s1 []int
      
            //:=声明
            s2 :=[]int{}
      
            var s3 []int = make([]int, 0)
            s4 :=make([]int, 0, 0)
            fmt.Println(s1, s2, s3, s4)
        }
      
      
        [] [] [] []

    .

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    func main() {
        //定义数组
        arr :=[...]int{0, 1, 2, 3, 4, 5, 6, 7}
    
        //切片取值
        fmt.Println(arr[2:6])
        fmt.Println(arr[:6])
        fmt.Println(arr[2:])
        fmt.Println(arr[:])
    }
    
    
    //[2 3 4 5]
    //[0 1 2 3 4 5]
    //[2 3 4 5 6 7]
    //[0 1 2 3 4 5 6 7]

    go切片可以向后扩展, 但不能向前扩展

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    func main() {
        //定义数组
        arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
        s1 := arr[2:6]
        fmt.Println(s1)
        s2 := s1[3:5]
        fmt.Println(s2)
        
        //切片添加元素
        s3 := append(s2,10)
        fmt.Println(s3)
        fmt.Println(arr)
    
        s4 := append(s3,11)
        fmt.Println(s4)
        fmt.Println(arr)
        s5:= append(s4,12)
        fmt.Println(s5)
        fmt.Println(arr)
    }
    
    //[2 3 4 5]
    //[5 6]
    //[5 6 10]
    //[0 1 2 3 4 5 6 10]
    //[5 6 10 11]
    //[0 1 2 3 4 5 6 10]
    //[5 6 10 11 12]
    //[0 1 2 3 4 5 6 10]

    内建函数copy()

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    func main() {
        //切片
        data := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        s1 := data[8:]
        s2 := data[:5]
        fmt.Println(s1)
        fmt.Println(s2)
    
        //将第二个拷贝到第一个里
        copy(s2, s1)
        fmt.Println(s2)
        fmt.Println(data)
    }
    
    //[8 9]
    //[0 1 2 3 4]
    //[8 9 2 3 4]
    //[8 9 2 3 4 5 6 7 8 9]

    5. Map

    • Map 是go内置的数据结构,是一种无序的键值对的集合,可以通过key快速找到value的值
    • 定义Map:
      • var 变量名 map[key的数据类型] value的数据类型
      • 创建map

            //package 声明开头表示代码所属包
            package main
        
            import "fmt"
        
            func main() {
                //声明map
                var mmp map[int]string
                fmt.Println(mmp == nil)
        
                //m2和m3是等价的
                m2 := map[int]string{}
                m3 :=make(map[int]string)
                fmt.Println(m2, m3)
        
                m4 :=make(map[int]string, 10)
                fmt.Println(m4)
            }
        
            //true
            //map[] map[]
            //map[]

    初始化map

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    func main() {
        //1. 定义同时初始化
        var m1 map[int]string = map[int]string{1:"超哥", 2:"最帅"}
        fmt.Println(m1)
    
        //2. 自动推导类型 :=
        m2 :=map[int]string{1:"超哥", 2:"最帅"}
        fmt.Println(m2)
    }
    
    //map[1:超哥 2:最帅]
    //map[1:超哥 2:最帅]

    键值操作

    //package 声明开头表示代码所属包
    package main
    
    func main() {
        m1 :=map[int]string{1:"111",2:"222"}
        
        //修改
        m1[1]="1111"
        //追加
        m1[3]="333"
    }

    6. 结构体

    • go语言没有class,只是个结构体struct
    • 结构体定义:
      • type 结构体名 struct{}
    • 结构体初始化

    //package 声明开头表示代码所属包
    package main

    import "fmt"
    
    //定义学生结构体
    type Student struct {
        id int
        name string
        sex byte
        age int
        addr string
    }
    
    func main() {
        //1.顺序初始化
        var s1 Student = Student{1,"约汉",'f',18,"bj"}
        fmt.Println(s1)
        s2 := Student{2,"接客",'m',20,"sh"}
        fmt.Println(s2)
        //s3 := Student{3,"撸死",'m',25}
    
        //2.指定初始化成员
        s4 := Student{id:4,age:26}
        fmt.Println(s4)
        fmt.Println(s4.id)
    
        //3.结构体作为指针变量初始化
        var s5 *Student = &Student{5,"接客",'f',20,"sh"}
        fmt.Println(s5)
        //指针类型访问变量
        //go底层自己实现了转换,下面2种都可以取指针对象的属性
        fmt.Println((*s5).id)
        fmt.Println(s5.id)
    
        s6 := &Student{6,"接客",'m',20,"sh"}
        fmt.Println(s6)
    }
    
    //{1 约汉 102 18 bj}
    //{2 接客 109 20 sh}
    //{4  0 26 }
    //4
    //&{5 接客 102 20 sh}
    //5
    //5
    //&{6 接客 109 20 sh}

    7. 结构体参数

    结构体可以作为函数参数传递

    //package 声明开头表示代码所属包
    package main
    
    import "fmt"
    
    type Student struct {
        id   int
        name string
        sex  string
        age  int
        addr string
    }
    
    //定义传递学生对象的方法
    func tmpStudent(tmp Student) {
        //修改id
        tmp.id = 250
        fmt.Println("tmp=", tmp)
    }
    
    //定义传递指针类型的对象的方法
    func tmpStudent2(p *Student) {
        //修改id
        p.id = 249
        fmt.Println("tmp2=", p)
    }
    
    func main() {
        var s Student = Student{1, "接客", "female", 20, "sz"}
        tmpStudent(s)
        fmt.Println("main s =", s)
        //传递指针地址
        tmpStudent2(&s)
        fmt.Println("main s2=", s)
    }
    
    //tmp= {250 接客 female 20 sz}
    //main s = {1 接客 female 20 sz}
    //tmp2= &{249 接客 female 20 sz}
    //main s2= {249 接客 female 20 sz}
     
     
  • 相关阅读:
    【论文阅读】Transformer及其在计算机视觉领域上的应用
    【学习笔记】asyncio的使用
    【论文阅读】Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization
    【论文阅读】Bag of Tricks for Image Classification with Convolutional Neural Networks
    【论文阅读】Bag of Tricks and A Strong Baseline for Deep Person Re-identification
    【论文阅读】主动学习 (Active Learning)
    可能有点用的东西
    .vimrc
    莫比乌斯反演 学习笔记
    对拍
  • 原文地址:https://www.cnblogs.com/yanghongtao/p/10970378.html
Copyright © 2020-2023  润新知