zoukankan      html  css  js  c++  java
  • 21天从Java转向Go之第五天——水滴石穿(复合数据类型)

    复合数据类型

    • 复合数据类型是由基本数据类型以各种方式组合而构成的。这章重点讲解四种复合数据类型。分别是数组、slice、map和结构体。

    • 数组和结构体都是聚合类型。它们的值由内存中的一组变量构成。数组的元素具有相同的类型。而结构体中的元素数据类型则可以不同。数组和结构体的长度是固定的。而slice和map都是动态数据结构,它们的长度在元素添加到结构中时可以动态增长。

    数组

    
    
    package main
    
    import (
    "fmt"
    "reflect"
    )
    
    var array [3]int
    
    type currency int
    const (
    RMB currency = iota
    EUR
    USD
    )
    
    func main() {
    array[0] = 22
    array[1] = 33
    array[2] = 44
    
    fmt.Println(array) //[22 33 44]
    for i, v := range array {
    fmt.Println(i, v)
    //0 22
    //1 33
    //2 44
    }
    for _, v := range array {
    fmt.Println(v) //22 33 44
    }
    
    //slice
    arr2:= []int{1,2,3}
    fmt.Println(reflect.TypeOf(arr2))
    fmt.Printf("arr2类型:%T\n",arr2)
    
    arr3:= [3]int{1,2,3}
    fmt.Println(reflect.TypeOf(arr3))
    fmt.Println(arr3)
    
    arr4:= [...]int{1,2,3}
    fmt.Println(reflect.TypeOf(arr4))
    fmt.Println(arr3 == arr4) //true 数组类型,长度相同才能比较
    fmt.Println(&arr3 == &arr4) //false
    
    money := [...]currency{RMB:8,USD:9,EUR:10}
    fmt.Println(money)
    for i, c := range money {
    fmt.Println(i,c)
    }
    
    //可以指定索引位置的元素值,其他位置是零值
    arr5:= [...]string{"11",10:"ssss","22"}
    fmt.Println(arr5)
    
    b:= [...]byte{1,2,3}
    zeroClear2(&b)
    fmt.Println("After zeroClear:",b)
    }
    
    func zeroClear(p *[3]byte) {
    for i := range p {
    p[i] = 0
    }
    }
    
    func zeroClear2(p *[3]byte) {
    *p = [3]byte{}
    }
    
    

    slice

    • slice表示一个拥有相同类型元素的可变长度的序列。slice通常写作[]T,看上去像没有指定长度的数组。

    • slice是一种轻量级的数据结构,可以用来访问数组的部分或全部的元素,而这个数组被称为slice的底层数组。

    • slice有三个属性:指针、长度和容量。指针指向数组的第一个可以从slice访问的元素,这个元素并不一定是数组的第一个元素。长度是指slice中元素的个数,不能超过slice的容量。容量的大小通常是从slice的起始元素到底层数组的最后一个元素间元素的个数。

    • Go的内置函数len和cap用来返回slice的长度和容量。

    • 因为slice包含了指向数组的指针,因此在函数传递参数时,函数内做的修改会影响到slice指向的底层数组。

    • 对一个切片再次slice[m:n]运算时,是对slice的指向的底层数组再计算(再切片运算)。slice[i]访问slice切片的第i个位置的元素,slice[:n] 如果n大于slice指向底层数组的容量cap,会导致程序宕机。如果大于len(slice)小于cap(slice),则会扩容slice

    
    
    package main
    
    import (
    "fmt"
    )
    
    var arr = [...]int{1,2,3,4,5,6,7,8,9}
    
    func main() {
    slice1 := arr[1:4]
    fmt.Println("slice1的len和cap分别是",len(slice1),cap(slice1)) //slice1的len和cap分别是 3 8
    fmt.Println("slice1:",slice1) //slice1: [2 3 4]
    slice2 := arr[2:8]
    fmt.Println("slice1的len和cap分别是",len(slice2),cap(slice2)) //slice1的len和cap分别是 6 7
    fmt.Println("slice2:",slice2) //slice2: [3 4 5 6 7 8]
    slice2[1] = 1//slice数组修改影响其他共用的底层数组
    fmt.Println("slice2:",slice2) //slice2: [3 1 5 6 7 8]
    fmt.Println("slice1:",slice1) //[2 3 1]
    
    //slice指向底层数组切片
    slice2 = slice2[:3]
    fmt.Println(slice2) //[3 1 5] 缩容
    
    slice2 = slice2[:7]
    fmt.Println(slice2) //[3 1 5 6 7 8 9] 扩容
    //slice2 = slice2[:8] //panic: runtime error: slice bounds out of range [:8] with capacity 7
    fmt.Println(slice2) //[3 1 5]
    
    //make函数
    //指定长度 容量不指定默认和长度相同
    ints := make([]int, 2)
    //分别指定len和cap
    ints2 := make([]int, 2,5)
    fmt.Println(ints) //[0 0]
    fmt.Println("ints","len:",len(ints),",cap:",cap(ints)) //ints len: 2 ,cap: 2
    fmt.Println("ints2","len:",len(ints2),",cap:",cap(ints2)) //ints2 len: 2 ,cap: 5
    
    //append函数 自动扩容
    ints = append(ints, 1)
    fmt.Println(ints) //[0 0 1]
    fmt.Println(len(ints), cap(ints)) // 3 4
    
    ints = append(ints, 1)
    fmt.Println(ints) //[0 0 1 1]
    fmt.Println(len(ints), cap(ints)) // 4 4
    
    ints = append(ints, 1)
    fmt.Println(ints)//[0 0 1 1 1]
    fmt.Println(len(ints), cap(ints)) //5 8
    //coupy函数 src复制到dst切片
    i := copy(ints, arr[0:4])
    fmt.Println("copy length:",i)
    fmt.Println("ints:",ints)
    }
    
    
    

    map

    • map[K]V K是和V是字典键和值对应的数据类型,键的类型必须是通过==可以判断的数据类型(切片不可以)。

    • 内置函数make可以用来初始化一个map

    
    
    package main
    
    import (
    "fmt"
    "sort"
    )
    
    var hashmap = make(map[int]string)
    
    func main() {
    hashmap[1] = "1"
    hashmap[2] = "2"
    hashmap[3] = "3"
    hashmap[4] = "4"
    hashmap[5] = "5"
    fmt.Println(hashmap)
    
    //使用字面量初始化map
    m := map[int]string{1: "22", 2: "222", 3: "2222"}
    fmt.Println(m)
    
    //移除元素delete
    delete(hashmap, 12)
    fmt.Println(hashmap)
    //赋值
    hashmap[1] += "呢哇 1"
    fmt.Println(hashmap)
    //无法获取map某元素的地址值 因为map是动态的 获取到的地址可能已经变成其他元素了
    //s := &hashmap[1]
    m2 := &hashmap
    fmt.Println(m2)
    //遍历
    for k, v := range hashmap {
    fmt.Println(k, v)
    }
    
    //按k的顺序遍历map
    keys := make([]int, 0, len(hashmap))
    for k := range hashmap {
    keys = append(keys, k)
    }
    sort.Ints(keys)
    for _, key := range keys {
    v := hashmap[key]
    fmt.Println("按k的顺序排序:v=", v)
    }
    
    newMap := make(map[string]string)
    newMap["sss"] = "sss"
    fmt.Println(newMap)
    
    //panic: assignment to entry in nil map
    //var newMap2 map[string]string
    //newMap2["sss"] = "ssss"
    //fmt.Println(newMap2)
    
    if _, ok := newMap["ssss"]; !ok {
    fmt.Println("not exist ele","ssss")
    }
    
    
    }
    
    

    结构体

    
    
    package main
    
    import (
    "encoding/json"
    "fmt"
    )
    
    type Man struct {
    h Human
    sex, gender int
    Human
    Hello string `json:"Hello"`
    }
    
    type Human struct {
    Age int
    height float32
    }
    
    func main() {
    v := new(Man)
    v.sex = 1
    v.h.height = 177.11
    v.h.Age = 28
    v.Age = 30
    v.height = 188
    v.gender = 1
    fmt.Println(*v)
    
    man := Man{h: Human{Age: 28, height: 177.11}, sex: 1, gender: 1, Human: Human{Age: 100, height: 100.00}}
    fmt.Println(man)
    //结构体的比较 成员变量都可比较才能比较
    fmt.Println(man == *v)
    man = *v
    fmt.Println(man)
    
    marshal, err := json.Marshal(*v)
    fmt.Println(err)
    fmt.Printf("%s\n", marshal)
    
    x := "{\"Hello\":\"111\"}"
    v2 := new(Man)
    json.Unmarshal([]byte(x), v2)
    fmt.Printf("%#v",v2)
    
    }
    
    
  • 相关阅读:
    Opengl编程指南第三章:视图
    OpenGL编程指南第四章:颜色
    OpenGL编程指南第七章:显示列表
    推荐:字体、排版简明入门
    OpenGL编程指南第八章:绘制像素、位图、字体和图像
    推荐:字体、排版简明入门
    OpenGL编程指南第五章:光照
    转载一篇密码学基本介绍
    ARM_异常和中断学习笔记
    ARM指令学习笔记
  • 原文地址:https://www.cnblogs.com/perkins/p/15614069.html
Copyright © 2011-2022 走看看