继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Go语言开发(三)、Go语言内置容器

holdtom
关注TA
已关注
手记 1871
粉丝 240
获赞 992


Go语言开发(三)、Go语言内置容器

一、Go语言数组

1、Go语言数组简介

Go语言提供了数组类型的数据结构。

数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,类型可以是任意的原始类型例如×××、字符串或者自定义类型。

相对于去声明number0, number1, ..., and number99的变量,使用数组形式numbers[0], numbers[1] ..., numbers[99]更加方便且易于扩展。

数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素索引为 0,第二个索引为 1,以此类推。

Go语言开发(三)、Go语言内置容器

2、Go语言数组声明

Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:

var variable_name [SIZE] variable_type

以上为一维数组的定义方式。数组长度必须是整数且大于0。例如以下定义了数组balance长度为10类型为float32:

var balance [10] float32

3、Go语言数组初始化

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

初始化数组中{}中的元素个数不能大于[]中的数字。

如果忽略[]中的数字不设置数组大小,Go语言会根据元素的个数来设置数组的大小:

var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

该实例与上面的实例是一样的,虽然没有设置数组的大小。

balance[4] = 50.0

以上实例读取了第五个元素。数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素索引为0,第二个索引为1,以此类推。

Go语言开发(三)、Go语言内置容器

4、Go数组元素访问

数组元素可以通过索引(位置)来读取。格式为数组名后加中括号,中括号中为索引的值。例如:

var salary float32 = balance[9]

以上实例读取了数组balance第10个元素的值。

以下演示了数组完整操作(声明、赋值、访问)的实例:

package main

import "fmt"

func main() {

   var n [10]int /* n 是一个长度为 10 的数组 */

   var i,j int

   /* 为数组 n 初始化元素 */

   for i = 0; i < 10; i++ {

      n[i] = i + 100 /* 设置元素为 i + 100 */

   }

   /* 输出每个数组元素的值 */

   for j = 0; j < 10; j++ {

      fmt.Printf("Element[%d] = %d\n", j, n[j] )

   }

}

5、Go语言多维数组简介

Go 语言支持多维数组,以下为常用的多维数组声明方式:

var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type

以下实例声明了三维的整型数组:

var threedim [5][10][4]int

6、Go语言二维数组声明

二维数组是最简单的多维数组,二维数组本质上是由一维数组组成的。二维数组定义方式如下:

var arrayName [ x ][ y ] variable_type

variable_type为Go语言的数据类型,arrayName为数组名,二维数组可认为是一个表格,x为行,y为列,下图演示了一个二维数组a为三行四列:

Go语言开发(三)、Go语言内置容器

二维数组中的元素可通过a[ i ][ j ]来访问。

初始化二维数组

多维数组可通过大括号来初始值。以下实例为一个3行4列的二维数组:

a = [3][4]int{

{0, 1, 2, 3} ,   /*  第一行索引为 0 */

{4, 5, 6, 7} ,   /*  第二行索引为 1 */

{8, 9, 10, 11}   /*  第三行索引为 2 */

}

访问二维数组

二维数组通过指定坐标来访问。如数组中的行索引与列索引,例如:

int val = a[2][3]

二维数组可以使用循环嵌套来输出元素:

package main

import "fmt"

func main() {

   /* 数组 - 5 行 2 列*/

   var a = [5][2]int{ {0,0}, {1,2}, {2,4}, {3,6},{4,8}}

   var i, j int

   /* 输出数组元素 */

   for  i = 0; i < 5; i++ {

      for j = 0; j < 2; j++ {

         fmt.Printf("a[%d][%d] = %d\n", i,j, a[i][j] )

      }

   }

}

7、数组参数传递

如果向函数传递数组参数,需要在函数定义时,声明形参为数组。数组参数传递为值传递,如果要在函数内部修改数组的元素的值,需要传递数组指针。通常,函数的数组参数的声明有两种方式:

A、形参指定数组大小

func sum(arr [5] int, size int) int{

   var c int = 0

   var i int

   for i = 0; i < size;i++{

      c += arr[i]

   }

   return c

}

B、形参不指定数组大小

 func getAverage(arr []int,size int) float32 {

   var i int

   var avg float32

   var sum int

   for i = 0; i < size; i++{

      sum += arr[i]

   }

   avg = float32(sum / size)

   return avg;

}

数组使用实例:

package main

import "fmt"

func getAverage(arr []int,size int) float32 {

   var i int

   var avg float32

   var sum int

   for i = 0; i < size; i++{

      sum += arr[i]

   }

   avg = float32(sum / size)

   return avg;

}

func sum(arr [5] int, size int) int{

   var c int = 0

   var i int

   for i = 0; i < size;i++{

      c += arr[i]

   }

   return c

}

func main() {

   var a [] int

   a = []int{1,2,6,90}

   var c float32

   c = getAverage(a,4)

   fmt.Println(c)

   var b [5] int

   b = [5]int{1,2,3,4,5}

   var d int = sum(b,5)

   fmt.Println(d)

}

二、Go语言切片

1、切片定义

Go语言切片是对数组的抽象。

由于Go数组的长度不可改变,Go中提供了一种灵活、功能强悍的内置类型切片("动态数组"),切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

可以声明一个未指定大小的数组来定义切片:

var identifier []type

使用make()函数来创建切片:

var slice1 []type = make([]type, len)

可以指定容量,其中capacity为可选参数。

make([]T, length, capacity)

len是数组的长度并且也是切片的初始长度。

2、切片初始化

s :=[] int {1,2,3 }

直接初始化切片,[]表示是切片类型,{1,2,3}初始化值依次是1,2,3,cap=len=3

s := arr[:]

使用数组arr的引用初始化切片s

s := arr[startIndex:endIndex]

将arr中从下标startIndex到endIndex-1下的元素创建为一个新的切片

s := arr[startIndex:]

缺省endIndex时将表示一直到arr的最后一个元素

s := arr[:endIndex]

缺省startIndex时将表示从arr的第一个元素开始

s1 := s[startIndex:endIndex]

通过切片s初始化切片s1

s :=make([]int,len,cap)

通过内置函数make()初始化切片s,[]int标识为其元素类型为int的切片

3、切片操作

切片是可索引的,并且可以由len()方法获取长度。

切片提供了计算容量的方法cap()可以测量切片最长可以达到多少。

package main

import "fmt"

func printSlice(x []int){

   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)

}

func main() {

   var slice1 [] int

   var slice2 [] int = make([]int, 6)

   slice1 = []int{1,2,3,4}

   slice2 = []int{1,2,3}

   printSlice(slice1)

   printSlice(slice2)

   s :=[] int {1,2,3 }

   fmt.Println(s)

}

4、nil切片

切片在未初始化前默认为nil,长度为0。

package main

import "fmt"

func printSlice(x []int){

   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)

}

func main() {

   var slice1 [] int

   printSlice(slice1)

   if slice1 == nil{

      fmt.Println("slice1 is nil")

   }

  }

5、切片截取

可以通过设置下限及上限来设置截取切片[lower-bound:upper-bound]。

package main

import "fmt"

func printSlice(x []int){

   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)

}

func main() {

   //创建切片

   numbers := []int{0,1,2,3,4,5,6,7,8}

   printSlice(numbers)

   //打印原始切片

   fmt.Println("numbers ==", numbers)

   //打印子切片从索引1(包含) 到索引4(不包含)

   fmt.Println("numbers[1:4] ==", numbers[1:4])

   //默认下限为0

   fmt.Println("numbers[:3] ==", numbers[:3])

   //默认上限为 len(s)

   fmt.Println("numbers[4:] ==", numbers[4:])

   numbers1 := make([]int,0,5)

   printSlice(numbers1)

   //打印子切片从索引0(包含)到索引2(不包含)

   number2 := numbers[:2]

   printSlice(number2)

   //打印子切片从索引2(包含)到索引5(不包含)

   number3 := numbers[2:5]

   printSlice(number3)

}

6、切片的本质

切片在本质上是数组的视图。切片是一个数组片段的描述,包含了指向数组的指针、片段的长度和容量(片段的最大长度)。切片与底层数组的关系如下:

Go语言开发(三)、Go语言内置容器

切片的内部实现如下:

Go语言开发(三)、Go语言内置容器

切片内部包含一个指向底层数组的某个位置的指针、切片长度信息、切片容量信息。

slice可以向后扩展,不可以向前扩展。

s[i]方式对切片数据进行引用不可以超越len(s),向后扩展不可以超越底层数组cap(s)。

package main

import "fmt"

func sliceExtend(){

   //定义数组

   arr := [...]int{0,1,2,3,4,5,6,7}

   s1 := arr[2:6]

   s2 := s1[3:5]

   s3 := arr[2:]

   s4 := arr[:6]

   s5 := arr[:]

   printSlice(s1)//len=4 cap=8 slice=[2 3 4 5]

   printSlice(s2)//len=2 cap=5 slice=[5 6]

   printSlice(s3)//len=8 cap=8 slice=[2 3 4 5 6 7]

   printSlice(s4)//len=6 cap=10 slice=[0 1 2 3 4 5]

   printSlice(s5)//len=10 cap=10 slice=[0 1 2 3 4 5 6 7]

   //对切片中数据进行修改,底层数组数据也被修改

   s1[0] = 100

   printSlice(s1)//len=4 cap=8 slice=[100 3 4 5]

   printSlice(s5)//len=10 cap=10 slice=[0 1 100 3 4 5 6 7]

   fmt.Println(arr)//[0 1 100 3 4 5 6 7]

   s1 = s1[2:6]

   printSlice(s1)//len=4 cap=6 slice=[4 5 6 7]

   //切片不能引用底层数组范围外的数据

   //printSlice(s1[2:9])//报错

}

func main() {

   sliceExtend()

}

7、切片追加和拷贝

如果想增加切片的容量,必须创建一个新的更大的切片并把原分片的内容都拷贝过来。

append()函数可以相一个切片追加一个或多个元素。

copy(dest,src)函数可以将dest切片拷贝到src切片。

追加元素时,如果切片超越了cap,系统会为切片分配一个更大的底层数组,每次需要重新分配底层数组时,底层数组的容量会翻倍增长。

package main

import "fmt"

func sliceOperate() {

   var numbers = [3]int{0,1}//数组

   s1 := numbers[1:]//切片

   s1[0] = 101//修改切片的元素的值

   printSlice(s1)//len=2 cap=2 slice=[101 0]

   fmt.Println(numbers)//[0 101 0]

   //向切片追加一个元素

   s1 = append(s1, 2)

   printSlice(s1)//len=3 cap=4 slice=[101 0 2]

   //向切片添加一个元素,已经超越cap,系统会为切片分配更大的底层数组

   s1 = append(s1, 3)

   printSlice(s1)//len=4 cap=4 slice=[101 0 2 3]

   fmt.Println(numbers)//[0 101 0]

   //同时添加多个元素,系统为切片分配新的底层数组

   s1 = append(s1, 4,5,6)

   printSlice(s1)//len=7 cap=8 slice=[101 0 2 3 4 5 6]

   fmt.Println(numbers)//[0 101 0]

   //创建切片numbers1,len与numbers切片相同,cap为2倍

   s2 := make([]int, len(s1), (cap(s1))*2)

   //拷贝numbers的内容到numbers1

   copy(s2,s1)

   printSlice(s2)//len=7 cap=16 slice=[101 0 2 3 4 5 6]

//将s2中的0删除

    s2 = append(s2[0:1], s2[2:]...)

    printSlice(s2)//len=6 cap=16 slice=[101 2 3 4 5 6]

//删除第一个元素

   front := s2[0]

   fmt.Println(front)//101

   s3 := s2[1:]

   printSlice(s3)//len=5 cap=15 slice=[2 3 4 5 6]

   //删除最后一个元素

   tail := s2[len(s2)-1]

   s4 := s2[:len(s2) - 1]

   fmt.Println(tail)//6

   printSlice(s4)//len=5 cap=16 slice=[101 2 3 4 5]

}

func main() {

   sliceOperate()

}

三、Go语言Map

1、Go语言Map简介

Ma是一种无序的键值对的集合。Map最重要的一点是通过key来快速检索数据。 

Map是一种集合,可以对其进行迭代。Map使用hash表来实现,Map是无序的,无法决定返回顺序。

2、Go语言Map定义

可以使用内建函数make,也可以使用map关键字来定义Map:

//声明变量,默认map是nil

var map_variable map[key_data_type]value_data_type

//使用make函数

map_variable := make(map[key_data_type]value_data_type)

如果不初始化map,会创建一个nil的map。nil的map不能用来存放键值对。

//map集合创建

var countryCapitalMap map[string]string//countryCapitalMap==nil

countryCapitalMap = make(map[string]string)//countryCapitalMap == empty map

3、Go语言Map操作

获取元素:map[key]

key不存在时,获得value类型的初始值。

用value,ok := map[key]来判断是否存在key。

使用range遍历key,遍历key,value对,遍历不保证顺序。

使用len获得map的元素个数.

map使用哈希表,必须可以比较相等。

除了slice、map、function的内置类型都可以作为key。struct类型如果不包含slice、map、func字段可以作为key。

delete()函数用于删除集合的元素, 参数为map和其对应的key。

package main

import "fmt"

func mapDemo(){

   //map集合创建

   var countryCapitalMap map[string]string

   countryCapitalMap = make(map[string]string)

   //map插入key-value对

   countryCapitalMap["France"] = "Paris"

   countryCapitalMap["Italy"] = "罗马"

   countryCapitalMap["Japan"] = "东京"

   countryCapitalMap["India"] = "新德里"

   //map值的修改

   countryCapitalMap["France"] = "巴黎"

   //输出国家首都信息

   for country := range countryCapitalMap {

      fmt.Println(country, "首都是", countryCapitalMap [country])

   }

   //查看元素在集合中是否存在

   captial, ok := countryCapitalMap["美国"]

   //如果确定是真实的,则存在,否则不存在

   if (ok) {

      fmt.Println("美国的首都是", captial)

   } else {

      fmt.Println("美国的首都不存在")

   }

}

func deleteMap(){

   //创建map

   countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"}

   fmt.Println("原始地图")

   //打印地图

   for country := range countryCapitalMap {

      fmt.Println(country, "首都是", countryCapitalMap [ country ])

   }

   //删除元素

   delete(countryCapitalMap, "France")

   fmt.Println("法国条目被删除")

   fmt.Println("删除元素后地图")

   //打印地图

   for country := range countryCapitalMap {

      fmt.Println(country, "首都是", countryCapitalMap [ country ])

   }

}

func lengthOfNoRepeatedSubString(str string)int{

    lastOccurred := make(map[rune]int)

    start := 0

    maxLength := 0;

    for i,ch := range  []rune(str){

        lastI,ok := lastOccurred[ch]

        if(ok && lastI >= start){

            start = lastI + 1

        }

        if i - start + 1 > maxLength{

            maxLength = i -start + 1

        }

        lastOccurred[ch] = i

    }

    return maxLength

}

func main() {

   mapDemo()

   deleteMap()

}

四、Go语言range

1、range简介

Go语言中range关键字用于for循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中,range返回元素的索引和索引对应的值,在集合中返回key-value对的key值。

2、rang使用实例

package main

import "fmt"

func rangeDemo(){

   //使用range遍历切片

   nums := []int{2, 3, 4}

   sum := 0

   //返回的切片的索引可以省略

   for _, num := range nums {

      sum += num

   }

   fmt.Println("sum:", sum)

   //在切片上使用range,返回index和值

   for i, num := range nums {

      if num == 3 {

         fmt.Println("index:", i)

      }

   }

   fmt.Println(sum)

   //使用range迭代map

   kvs := map[string]string{"a": "apple", "b": "banana"}

   for k, v := range kvs {

      fmt.Printf("%s -> %s\n", k, v)

   }

   //使用range遍历Unicode字符串,返回字符的索引与字符(Unicode的值)本身

   for i, c := range "go,你好" {

      fmt.Printf("%d %c\n",i,c)

   }

}

func main() {

   rangeDemo()

   a := map[int]string{1:"hello",2:"world"}

   for k,v := range a{

   fmt.Println(k,v)

}

}

©著作权归作者所有:来自51CTO博客作者天山老妖S的原创作品,如需转载,请注明出处,否则将追究法律责任


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP

热门评论

写的很好的学习了,受益匪浅

查看全部评论