zoukankan      html  css  js  c++  java
  • 【Go】学习笔记兼吐槽(3)

     

     

    Go:学习笔记兼吐槽(1)

    Go:学习笔记兼吐槽(2)

    Go:学习笔记兼吐槽(3)

     

     


     

    数组

    Golang 中,数组是值类型。

    数组的声明

    var arr [10]int

    数组的初始化

    var arr1 [3]int = [3]int{123}
    var arr2 = [3]int{456}
    var arr3 = [...]int{789}
    var arr4 = [...]int{110022003300}

    用 for-range 遍历数组

    基本语法:

    for index, value := range 数组变量{
    }

    其中:index 为数组下标,value 是该下标位置的值。

    长度是数组类型的一部分

    长度是数组类型的一部分,就是说数组不可以脱离长度而存在。听起来不太明白,我们来看下面的一个示例就明白了,这真的是一个大坑。

    假设,我们现在要写一个排序函数,C# 中,我们会这样定义:

    public void Sort(int[] array)
    {
    }

    但是,在 Golang 中,这是不行的。

    func main() {
        var arr [3]int = [3]int{123}
        Sort(arr)
    }

    func Sort(array []int){
    }

    Sort(arr) 这句编译就会报错:cannot use arr (type [3]int) as type []int in argument to Sort。因为 Sort 函数的参数 array []int 是一个切片,不是数组,将数组作为参数传给 Sort 就会报类型不匹配。

    如果一定需要以数组作为参数传递,Sort 的参数必须定义成数组,就是带上长度:

    func Sort(array [3]int){
    }

    这么定义这函数还有啥用?吐槽一万字…
    虽然有切片可以用来实现我们的功能,但是,数组就变得有点鸡肋了。

    切片 slice

    切片是引用类型,类似于 C# 中的 list 。内部维护一个数组,当追加元素超出切片容量时,切片自动扩容。(跟 list 是一样的机制。)

    切片的声明

    var arr []int

    切片的使用

    //方法一:
    var arr1 [5]int = [5]int{12345}
    slice1 := arr1[13]    //这里的使用跟 Python 很像

    //方法二:
    var slice2 []int = make([]int510)

    //方法三:
    var slice3 []int = []int{12345}

    使用 make 初始化切片,make 的三个参数依次为:切片数据类型,切片长度,切片容量。

    给切片追加元素

    //方法一:追加一个或多个同类型
    var slice1 []int = make([]int510)
    slice1 = append(slice1, 100200)
    fmt.Printf("%v ", slice1)

    //方法二:追加切片(只能是切片,不可以是数组)
    var slice2 []int = []int{12345}
    slice1 = append(slice1, slice2...)    // 三个点不能少
    fmt.Printf("%v", slice1)

    append 函数也很搞笑,其返回值必须赋值给一个切片,否则编译都过不了。如果一个切片调用 append 追加元素后,又赋值给了自己(我们一般也是这么用的),则切片的地址不会发生改变(除非发生了扩容)。如果 切片 1 调用 append 后赋值给了 切片 2,则 切片 1 保持未追加前的原样不变,另生成一个新的切片赋给 切片 2

    示例:

    var slice1 []int = make([]int510)
    fmt.Printf("%v %p ", slice1, &slice1)    // [0 0 0 0 0] 0xc000004460

    slice1 = append(slice1, 100)
    fmt.Printf("%v %p ", slice1, &slice1)    // [0 0 0 0 0 100] 0xc000004460

    slice2 := append(slice1, 200)
    fmt.Printf("%v %p ", slice1, &slice1)    // [0 0 0 0 0 100] 0xc000004460
    fmt.Printf("%v %p ", slice2, &slice2)    // [0 0 0 0 0 100 200] 0xc0000044e0

    映射 map

    就是字典。

    map 的声明

    var m map[int]string

    map 的使用

    // 方式一:使用 make 函数
    m := make(map[int]string10)

    // 方式二:直接赋值
    m := map[int]string{
        1"张三",
        2"李四",
    }

    make 方法的第一个参数是 map 的数据类型,第二个参数是初始容量。

    注意,如果是方式二直接赋值,最后一个 key-value 后面也要加逗号。

    删除元素

    delete(map, key)

    参数:

    • map:要删除元素的 map
    • key:要删除的 key,当 key 在 map 中不存在时,不进行任何操作,也不报错。

    Golang 中 map 没有类似其他语言中的 clear 方法,如果要一次性删除全部元素,可遍历 map 逐一删除,或者重新 make 一下使其指向一个新的内存空间。

    查找元素

    val, finded := m[1]
    if finded{
        fmt.Println(val)
    }

    遍历元素

    只能用 for-range 遍历

    for k, v := range m{
        fmt.Printf("%v: %v ", k, v)
    }

    结构体 struct

    • Golang 中没有类(class),Go 中的结构体(struct)和其他语言中的类有同等的地位。可以理解为 Golang 是基于 struct 来实现面向对象。
    • 结构体是值类型。结构体的所有字段在内存中是连续的。

    结构体的声明

    type 结构体名称 struct{
        field1 type
        field2 type
    }

    结构体的使用

    type Person struct{
        Name string
        Age int
    }

    // 方式一:
    p1 := Person{}
    p1.Name = "Tom"
    p1.Age = 10

    // 方式二
    p2 := Person{"Jerry", 5}

    // 方式三
    p3 := Person{Name: "张三", Age: 30}
    // 或
    p3 := Person{
    Name: "张三", 
    Age: 30,        // 注意这里要加逗号,否则会被默认加上分号
    }

    结构体指针

    // 方式一:
    var person1 *Person = new(Person)
    (*person1).Name = "Tom"
    (*person1).Age = 10
    fmt.Println(*person1)

    // 方式二:
    person2 := new(Person)
    person2.Name = "Tom"
    person2.Age = 10
    fmt.Println(*person2)

    // 方式三:
    var person3 *Person = &Person{"Jerry"5}
    fmt.Println(*person3)

    这三种方式定义的都是结构体指针,因为是指针,所以给字段赋值的标准方式应该是方式一的写法,但是 Go 的设计者为了程序员使用方便,给出了一个语法糖,使 (*person1).Name = "Tom" 简化为 person1.Name = "Tom",即方式二的写法,编译时,会自动加上取值运算。而方式三的写法可以直接赋值。

    结构体标签

    struct 的每个字段上可以定义一个标签(tag),该标签可以通过反射机制获取,最常见的使用场景就是序列化和反序列化。

    type Person struct{
        Name string `json:"name"`
        Age int `json:"age"`
    }

    p := Person{"张三"30}
    jsonStr, err := json.Marshal(p)
    if err == nil {
        fmt.Println(string(jsonStr)) // {"name":"张三","age":30}
    }

    自定义数据类型

    为了简化数据类型定义,Golang 支持自定义数据类型。

    基本语法:

    type 自定义数据类型名 数据类型  // 相当于起了一个别名

    示例:

    type myint int  //这时 myint 就等价于 int,但是 Go 会认为他们还是两个类型
    type mySum func(intint) int  //这时 mySum 就等价于一个函数类型

    自定义数据类型跟原类型虽然在我们的理解上是一样的,但是 Golang 会认为它们是两种不同的数据类型。这导致这两种类型是无法直接进行比较的,必须强转。

  • 相关阅读:
    Linux Shell脚本编程基础
    UBoot常用命令及内核下载与引导
    经典C面试真题精讲
    文本相似度分析(基于jieba和gensim)
    python中lambda,map,reduce,filter,zip函数
    机器学习-——损失函数
    Tensorflow中的数据对象Dataset
    github 相关操作知识
    机器学习——LightGBM
    机器学习——超参数搜索
  • 原文地址:https://www.cnblogs.com/gl1573/p/10334847.html
Copyright © 2011-2022 走看看