加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959

数组 Arrays

数组是同一种数据类型的固定长度的序列。

数组是值类型,因此改变副本的值,不会改变本身的值;

当作为方法的入参传入时将复制一份数组而不是引用同一指针。

通过从0开始的下标索引访问元素值。

数组定义

var a []int
a = make([]int, )
var a1 []int = []int{, , , , } //len:5 content:[1 2 3 4 5]
var a2 = []int{, , , , } //len:5 content:[1 2 3 4 5]
var a3 = [...]int{, , , , } //len:5 content:[1 2 3 4 5]
var a4 = [...]int{: , : } //len:3 content:[0 100 200]
var a5 = [...]string{: "nick", : "dawn"} //len:3 content:[ nick dawn]

数组定义后,长度不能变。

长度是数组类型的一部分,具有不同长度的数组,其类型是不同的。

因此,var a[5] int 和 var a[9]int 是不同的类型。

数组使用

通过下标访问,超出会报错

arr := []int{, , }
//fmt.Println(arr[5]) //报错

通过for遍历数组元素

func main()  {
arr := []int{, , }
for i:=; i<len(arr); i++ {
fmt.Println(arr[i]) //
}
for i,v := range arr{
fmt.Printf("index[%d]:content[%v]\n", i, v)
}
}

值类型数组赋值,改变副本不会改变自身

func main()  {
arr := []int{, , }
arr2 := arr
arr2[] =
fmt.Println(arr) //[1 2 3 0 0]
fmt.Println(arr2) //[10 2 3 0 0]
}
package main

import (
"fmt"
) func test1(n int) {
var a []int
a = make([]int, n) a[] =
a[] = for i := ; i < n; i++ {
a[i] = a[i-] + a[i-]
}
for _, v := range a {
fmt.Println(v)
}
} func main() {
test1()
}

栗子(斐波那契数列)

二维数组

多维数组,二维数组举例

var a1 [][]int

二维数组遍历

func main() {
var a1 [][]int = [...][]int{{, , , , }, {, , , , }} for row, v := range a1 {
for col, v1 := range v {
fmt.Printf("(%d,%d)=%d ", row, col, v1)
}
fmt.Println()
}
}

切片 Slices

切片是长度可变、容量固定的相同的元素序列。

切片是数组的一个引用,因此切片是引用类型。

因此在当传递切片时将引用同一指针,修改值将会影响其他的对象。

slice 与 array 接近,但是在新的元素加入的时候可以增加长度。slice 总是指向底层的一个 array。slice本身不是数组,slice 是一个指向 array的指针。

切片定义

创建切片跟创建数组唯一的区别在于 Type 前的“ [] ”中是否有数字,为空,则代表切片,否则则代表数组。

s1 := [] int{, , }          //直接初始化切片,[]表示是切片类型,初始化值依次是1,2,3.其cap=len=3
s2 := arr[:] //初始化切片s2,是数组arr的引用
s3 := arr[startIndex:endIndex] //将arr中从下标startIndex到endIndex-1下的元素创建为一个新的切片
s4 := arr[startIndex:] //缺省endIndex时将表示一直到arr的最后一个元素
s5 := arr[:endIndex] //缺省startIndex时将表示从arr的第一个元素开始
s6 := s1[startIndex:endIndex] //通过切片s6初始化切片截取s1
s7 := make([]int, len, cap) //通过内置函数make()初始化切片s,cap可以省略(省略时,值等同于len)

len() 与 cap()

长度是指已经被赋过值的最大下标+1,可通过内置函数len()获得。

容量是指切片目前可容纳的最多元素个数,可通过内置函数cap()获得。

arr := []int{, , }
fmt.Println(len(arr)) //
fmt.Println(cap(arr)) //

切片使用

遍历及修改

for i, v := range slice0 {
slice0[i] = strings.ToUpper(v)
fmt.Printf("index[%d]content[%s,%s]\n", i, v, slice0[i])
}

append 及 copy

append操作:slice可以在尾部追加元素,甚至还可以将一个slice追加到另一个slice的尾部,如果最终的长度没有超过原始的slice,那么append操作将返回原来的slice,否则将重新分配内存地址。

copy操作:copy操作返回复制的元素的个数,复制的数量是len(src)和len(dst)中最小的值。

slice := []int{, }
fmt.Printf("len[%d],content:%v\n", len(slice), slice) //len[2],content:[1 2]
slice = append(slice, , , , )
fmt.Printf("len[%d],content:%v\n", len(slice), slice) //len[6],content:[1 2 5 6 8 9] slicecp := make([]int, len(slice))
fmt.Printf("len[%d],content:%v\n", len(slice), slice) //len[6],content:[1 2 5 6 8 9]
n := copy(slicecp, slice)
fmt.Printf("len[%d],content:%v, retN:%d\n", len(slice), slice, n) //len[6],content:[1 2 5 6 8 9], retN:6
slicecp[] =
fmt.Printf("len[%d],content:%v\n", len(slice), slice) //len[6],content:[1 2 5 6 8 9]
fmt.Printf("len[%d],content:%v\n", len(slicecp), slicecp) //len[6],content:[10 2 5 6 8 9] sliceN := append(slice, slicecp...)
fmt.Printf("len[%d],content:%v\n", len(sliceN), sliceN) //len[12],content:[1 2 5 6 8 9 10 2 5 6 8 9]

值类型修改值会影响本身。

slice0 := []string{"a", "b", "c", "d", "e"}
slice1 := slice0
slice1[] = "Nick"
fmt.Println(slice0) //[Nick b c d e]
fmt.Println(slice1) //[Nick b c d e]

内存布局与扩容

切片是引用类型,指针内部只向一个数组。

代码实现,内存地址表示是同一块地址。

func main() {
var a []int = []int{, , , , }
s := a[:]
fmt.Printf("a=%p, s=%p \n", &(a[]), s) //a=0xc420016188, s=0xc420016188
s = append(s, , , )
fmt.Printf("a=%p, s=%p \n", &a[], s) //a=0xc420016188, s=0xc4200141c0
}

切片的长度是可变的,那自动扩容是怎样的机制呢?

是 double(双倍),看下面代码。

func main() {
var a []int = [...]int{, , , , }
s := a[:]
fmt.Println(cap(s), len(s)) //4 4
s = append(s, , , )
fmt.Println(cap(s), len(s)) //8 7
s = append(s, )
fmt.Println(cap(s), len(s)) //8 8
s = append(s, )
fmt.Println(cap(s), len(s)) //16 9
s = append(s, , , , )
fmt.Println(cap(s), len(s)) //16 13
s = append(s, , , , , , )
fmt.Println(cap(s), len(s)) //32 19
}
package main

import (
"fmt"
) type slice struct {
pre *[]int
len int
cap int
} func make1(s slice, cap int) slice {
s.pre = new([]int)
s.len =
s.cap = cap
return s
} func modify(s slice) {
s.pre[] =
} func testSlice() {
var s1 slice
s1 = make1(s1, ) s1.pre[] =
modify(s1) fmt.Println(s1.pre)
} func main() {
testSlice()
}

模仿切片

map

map在Go语言中是作为一种内建类型存在。

key-value的数据结构,又叫字典或关联数组。

map是引用类型。

map声明是不会分配内存的,需要make初始化。

map声明初始化

声明

var a map[keytype]valuetype
var a map[string]string
var a map[string]int
var a map[int]string
var a map[string]map[string]string  //嵌套

声明并初始化

var a map[string]string
a = make(map[string]string, ) a := make(map[string]string, )
a := make(map[string]string) var a map[string]string = map[string]string{}
var a map[string]string = map[string]string{
"A": "A",  //注意是逗号
}

map 使用

增删改查

m["name"] = "Nick"   // "create"
delete(m, "name") // "delete"
m["name"] = "Dawn" // "update"
name := m["name"] // "read"

读取不异常

name, errbool := m["name"]
if !errbool {
m["name"] = "Nick"
}

二维map

func modify(a map[string]map[string]string) {
_, ok := a["name"]
if !ok {
a["name"] = make(map[string]string)
}
a["name"]["Nick"] = "suoning"
a["name"]["Nicky"] = "manyRou"
} func testMap3() {
var a map[string]map[string]string
a = make(map[string]map[string]string, ) //初始化一维
a["name"] = make(map[string]string) //初始化二维 modify(a)
fmt.Println(a)
}

slice of map

Items := make([]map[int][int], )
For i := ; i < ; i++ {
items[i] = make(map[int][int])
}

map 排序

  1. 先获取所有key,把key进行排序
  2. 按照排序好的key,进行遍历
import "sort"

func testMapSort() {
var a map[int]int
a = make(map[int]int, ) a[] =
a[5] =
a[] =
a[] =
a[9] = var keys []int
for k, _ := range a {
keys = append(keys, k)
} sort.Ints(keys) for _, v := range keys {
fmt.Println(v, a[v])
}
}

map 反转

初始化另外一个map,把key、value互换即可

func testMapSort1() {
var a map[string]int
var b map[int]string a = make(map[string]int, )
b = make(map[int]string, ) a["name"] =
a["ege"] = for k, v := range a {
b[v] = k
} fmt.Println(b)
}

Go语言学习笔记(三)数组 & 切片 & map的更多相关文章

  1. Go语言学习笔记十一: 切片(slice)

    Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...

  2. Go语言学习笔记三: 常量

    Go语言学习笔记三: 常量 定义常量 常量就是在声明后不能再修改的量. const x int = 100 const y string = "abc" const z = &qu ...

  3. 【GO】GO语言学习笔记三

    7.数组: 几乎是最常用的数据类型了... 数组就是指一系列同一类型数据 的集合.数组中包含的每个数据被称为数组元素(element),一个数组包含的元素个数被称为数 组的长度. 常规的数组声明方法: ...

  4. Scala入门学习笔记三--数组使用

    前言 本篇主要讲Scala的Array.BufferArray.List,更多教程请参考:Scala教程 本篇知识点概括 若长度固定则使用Array,若长度可能有 变化则使用ArrayBuffer 提 ...

  5. Go语言学习笔记(4)——数组和切片

    1 数组的特点: 长度固定.元素数据类型相同.下标从0开始 1.1 声明和初始化: var array_name [size] type         var arr1 [10] float32   ...

  6. Go语言学习笔记(三) [控制结构、内建函数]

    日期:2014年7月21日   一.控制结构   1.Go中,只有几个控制结构,它没有do或者while循环,有for,灵活的switch语句和if,在switch中可以接受像for那样可选的初始化语 ...

  7. C语言学习笔记 (004) - 数组名和数组首地址(转)

    一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址.指针变量既然可以指向变量,当然也可以指向数组和数组元素(把数据起始地址或某一元素的地址放到一个指针变量中) ...

  8. c语言学习笔记 函数数组传递笔记

    今天学习c语言的一个小例子,果然还是陷入了php的编程习惯里,这里记录一下. #include <stdio.h> //例子很简单,就是编写一个函数把传递进来的数组里的值都赋值为1而已 / ...

  9. c语言学习笔记三

    第三章,函数 字符串函数 //strcmp int my_strcmp(char *str1,char *str2) {   while(*str1 = = *str2)   /*不可用while(* ...

  10. C语言学习笔记 (007) - 数组指针和通过指针引用数组元素的方法总结

    1.数组指针:即指向数组的指针 那么, 如何声明一个数组指针呢? ]; /*括号是必须写的,不然就是指针数组:10是数组的大小*/ 拓展:有指针类型元素的数组称为指针数组. 2.通过指针引用数组元素的 ...

随机推荐

  1. 全景智慧掌上城,飞入寻常百姓家——VR全景智慧城市

    随着腾讯和阿里陆续将AR技术加入到新年抢红包大战之中,人们对于VR.AR未来的应用空间又多了一些想象.同传统的基于二维元素的抢红包不同,借助VR.AR的技术能够让用户获得一种更加真切的体验,这种体验相 ...

  2. C#码农的大数据之路 - 使用C#编写MR作业

    系列目录 写在前面 从Hadoop出现至今,大数据几乎就是Java平台专属一般.虽然Hadoop或Spark也提供了接口可以与其他语言一起使用,但作为基于JVM运行的框架,Java系语言有着天生优势. ...

  3. 一天搞定CSS:css选择器--07

    选择器:是指选择标签的方法 1.选择器类型 2.id选择器 代码演示 <!DOCTYPE html> <html> <head> <meta charset= ...

  4. Java IO流--练习2

    1)写一个Java程序,输入3个整数,并求出三个数的最大数和最小数 代码: package 第十二章IO流; import java.io.BufferedReader; import java.io ...

  5. Python使用PyMysql操作数据库

    安装 pip install -U pymysql 连接数据库 连接数据库有两种不同的格式 直接使用参数 代码如下 import pymysql.cursors connection = pymysq ...

  6. python不使用第三方变量,交换两个变量的值

    #不使用第三个变量交换两个变量的值 a=1 b=2 a,b=b,a#python的直接交换 #另一种交换方法 a=a+b#a=3 b=2 b=a-b#a=3 b=1 a=a-b#a=2 b=1 pri ...

  7. datagrid 添加、修改、删除(转载)

    原链接:JQueryEasyUI学习笔记(十)datagrid 添加.修改.删除 基于datagrid框架的删除.添加与修改: 主要是批量删除,双击表单修改.选中行修改,增加行修改,再有就是扩展edi ...

  8. Spring学习(1)----入门学习(附spring-framework下载地址)

    (一)Spring是什么 Spring是一个开源框架,为了解决企业应用开发的复杂性而创建的,但现在已经不止应用于企业应用 是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架- 从大小和开销 ...

  9. Java并发编程之synchronized

    在Java编程中,为了保证线程安全,有3种不同的思路1.互斥同步:包括synchronized和lock等. 2.非阻塞同步:如AtomicInteger的increaseAndGet()方法等. 3 ...

  10. 14.Java中的Future模式

    jdk1.7.0_79  本文实际上是对上文<13.ThreadPoolExecutor线程池之submit方法>的一个延续或者一个补充.在上文中提到的submit方法里出现了Future ...