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)

}

原文地址:https://www.cnblogs.com/perkins/p/15614069.html