go 基础 -2

数组

数组是同一种数据类型元素的集合。 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。

// 定义
var 数组变量名 [元素数量]类型
//定义方法1,预先设置数组长度
var a [3]int
//定义方法2,让编辑器自行推断
var b [...]int{1, 2, 4}
//用索引值来初始化数组
var a int{1: 2, 6:999}

//遍历数组
func main() {
    var a = [...]string{"北京", "上海", "深圳"}
    // 方法1:for循环遍历
    for i := 0; i < len(a); i++ {
        fmt.Println(a[i])
    }

    // 方法2:for range遍历
    for index, value := range a {
        fmt.Println(index, value)
    }
}

 

多维数组

Go语言是支持多维数组的,我们这里以二维数组为例(数组中又嵌套数组)

注意: 多维数组只有第一层可以使用...来让编译器推导数组长度

func main() {
    a := [3][2]string{
        {"北京", "上海"},
        {"广州", "深圳"},
        {"成都", "重庆"},
    }
    fmt.Println(a)  //[[北京 上海] [广州 深圳] [成都 重庆]]
    fmt.Println(a[2][1])  //支持索引取值:重庆
}


// 遍历
func main() {
    a := [3][2]string{
        {"北京", "上海"},
        {"广州", "深圳"},
        {"成都", "重庆"},
    }
    for _, v1 := range a {
        for _, v2 := range v1 {
            fmt.Printf("%s\t", v2)
        }
        fmt.Println()
    }
}

数组是值类型,赋值和传参会复制整个数组。所以改变数组的值,不会改变数组本身

func main()  {
   var a  = [3]int{11, 22, 33}
   test1(a)
   fmt.Println(a)  // [11 22 33]
}

func test1(x [3]int)  {
   x[0] = 111
   fmt.Println(x)  // [111 22 33]
}

 

切片

切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。
切片是一个引用类型,它的内部结构包含地址、长度和容量。

// 定义
var name []T

var a []int  //声明一个切片
var a = []int{}  // 申明一个切片并初始化
//切片只有初始化之后才能使用

//len()函数求长度  cap()函数求容量
var a = []int {1,2,3}
fmt.Println(len(a))  // 3
fmt.Println(cap(a))  //  3


// 切片表达式
// 对于数组或字符串,如果0 <= low <= high <= len(a),则索引合法,否则就会索引越界(out of range)
// 对切片再执行切片表达式时(切片再切片),high的上限边界是切片的容量cap(a),而不是长度,尽量在定义时就确定容量,防止在程序运行时增加
// 下面的代码会构造与简单切片表达式a[low: high]相同类型、相同长度和元素的切片。
// 会将得到的结果切片的容量设置为max-low。
// 在完整切片表达式中只有第一个索引值(low)可以省略;它默认为0。
a[low : high : max]

func main() {
    a := [5]int{1, 2, 3, 4, 5}
    t := a[1:3:5]
    fmt.Printf("t:%v len(t):%v cap(t):%v\n", t, len(t), cap(t))
}  // t:[2 3] len(t):2 cap(t):4

// make函数构造切片
// T:切片的元素类型  size:切片中元素的数量  cap:切片的容量
make([]T, size, cap)

func main() {
    a := make([]int, 2, 10)
    fmt.Println(a)      //[0 0]
    fmt.Println(len(a)) //2
    fmt.Println(cap(a)) //10
}
// 代码中a的内部存储空间已经分配了10个,但实际上只用了2个。 容量并不会影响当前元素的个数,所以len(a)返回2,cap(a)则返回该切片的容量


//判断切片是否为空
len(s) == 0

// append为切片动态添加元素
var s []int
append(s, 1)

//go中没有删除切片元素的方法,需利用切片的特性来删除
func main() {
   a := []int{1,2,3,4}
   // 删除索引为2的元素
   a = append(a[:2], a[3:]...)
   fmt.Println(a)   // {1,2,4}
}
//从切片a中删除索引为index的元素,操作方法是
a = append(a[:index], a[index+1:]...)
// 删除切片中的元素其实是把删除元素后面的元素向前一位复制一份
// 把长度修改为一样后,原来的值
s := []int{1, 2, 3}
fmt.Println(s) // [1 2 3]
fmt.Printf("%p \n",s) //0xc00009e140
s = append(s[:1], s[2:]...)
fmt.Println(s) // [1 3]
fmt.Printf("%p \n",s) //0xc00009e140
s = s[:3]
fmt.Println(s) // [1 3 3]
fmt.Printf("%p \n",s) //0xc00009e140

 

 

map

map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。map是无序的。

// 定义
map[KeyType]ValueType
map 默认值为nil
// 定义完成后需要进行初始化,cap表示容量
make(map[KeyType]ValueType, [cap])
//也可以在声明的时候填充元素
user := [string]string{
    "a" : "1"
    "b" : "2"
}


// 判断某个key是否存在
func main() {
   scoreMap := make(map[string]int, 8)
   scoreMap["a"] = 10
   scoreMap["b"] = 20
   fmt.Println(scoreMap)
   fmt.Println(scoreMap["a"])
   fmt.Printf("%T \n", scoreMap)
   v, ok := scoreMap["a"]
   if ok {
      fmt.Println(v)
   } else {
      fmt.Println("nonono")
   }
}


// map的遍历
func main() {
   scoreMap := make(map[string]int, 8)
   scoreMap["a"] = 10
   scoreMap["b"] = 20
   for k, v := range scoreMap {
      fmt.Println(k, v)
   }
}
//只需要key时
func main() {
   scoreMap := make(map[string]int, 8)
   scoreMap["a"] = 10
   scoreMap["b"] = 20
   for k := range scoreMap {
      fmt.Println(k)
   }
}
//只需要value时
func main() {
   scoreMap := make(map[string]int, 8)
   scoreMap["a"] = 10
   scoreMap["b"] = 20
   for _, v := range scoreMap {
      fmt.Println(v)
   }
}


// 删除键值对
func main() {
   scoreMap := make(map[string]int, 8)
   scoreMap["a"] = 10
   scoreMap["b"] = 20
   delete(scoreMap, "a")
   for k, v := range scoreMap {
      fmt.Println(k, v)
   }
}


// 按指定顺序遍历map
func main() {
    var scoreMap = make(map[string]int, 10)

    for i := 0; i < 5; i++{
        key := fmt.Sprintf("stu%02d", i) //生产str开头的字符串
        value := rand.Intn(10) // 0-99的随机整数
        scoreMap[key] = value
    }

    for k, v := range scoreMap {
        fmt.Println(k, v)
    } 
    //stu01 7
    //stu03 9
    //stu04 1
    //stu00 1
    //stu02 7

    // 取出map中的key存入切片中
    var keys = make([]string, 0, 10)
    for key := range scoreMap{
        keys = append(keys, key)
    }
    fmt.Println(keys) // [stu00 stu02 stu01 stu03 stu04]

    //对切片进行排序,用sort
    sort.Strings(keys)
    fmt.Println(keys)  //[stu00 stu01 stu02 stu03 stu04]
    for _, key := range keys {
        fmt.Println(key, scoreMap[key])
    }
    //stu00 1
    //stu01 7
    //stu02 7
    //stu03 9
    //stu04 1
}

 

元素类型为map的切片

func main() {
   // 元素类型为map的切片
   var mapSlice = make([]map[string]int, 8 ,8) //只是完成了切片的初始化
   fmt.Println(mapSlice[0] == nil) // true
   // 还需要完成map元素的初始化
   mapSlice[0] = make(map[string]int, 8)
   mapSlice[0]["a"] = 1
   fmt.Println(mapSlice) // [map[a:1] map[] map[] map[] map[] map[] map[] map[]]
   fmt.Printf("%T \n", mapSlice) //[]map[string]int

}

 

值为切片的map

func main() {
   var sliceMap = make(map[string][]int, 8) //只初始化了map
   v, ok := sliceMap["haha"]
   if ok {
      fmt.Println(v)
   } else {
      sliceMap["haha"] = make([]int, 8) //完成切片的初始化
      sliceMap["haha"][0] = 1
      sliceMap["haha"][2] = 3
   }
   fmt.Println(sliceMap) //map[haha:[1 0 3 0 0 0 0 0]]

   for k, v :=range sliceMap{
      fmt.Println(k, v)
   } // haha [1 0 3 0 0 0 0 0]
}

 

练习

// 写出结果
func main() { type Map map[
string][]int m := make(Map) s := []int{1, 2} s = append(s, 3) // s={1,2,3} fmt.Printf("%+v\n", s) m["q1mi"] = s s = append(s[:1], s[2:]...) // 删除了s中索引为2的值,索引s={1,3} fmt.Printf("%+v\n", s) // s={1,3}

   fmt.Printf("%+v\n", m["q1mi"]) // s{1,3,3} m["q1mi"]的长度是3,删除切片中的元素就是把后面的元素往前复制了一个,所以第三个还是3
}

//参考https://blog.csdn.net/qq_41580831/article/details/104055663

// 统计字符中单词出现的次数
func main() {
var s = "how do you do"
var wordCount = make(map[string]int, 10)
words := strings.Split(s, " ")
// 将s中的字符根据空格为区分,隔开写入words
fmt.Println(words)
for _, word := range words {
v, ok := wordCount[word]
if ok {
wordCount[word] = v + 1
} else {
wordCount[word] = 1
}
}
for k, v := range wordCount {
fmt.Println(k, v)
}
}
 

 

参考 https://www.liwenzhou.com/posts/Go/go_menu/ 整理记录

 

posted @ 2020-04-12 22:26  nernogno  阅读(132)  评论(0编辑  收藏  举报