Golang 数组、切片、映射
定义数组
var arr1 [5]int //整型类型
fmt.Println(arr1) //[0 0 0 0 0]
//赋值
arr1 = [5]int{1, 2, 3, 4, 5}
fmt.Println(arr1) //[1 2 3 4 5] var arr2 [6]*int //整型指针数组
fmt.Println(arr2) //[<nil> <nil> <nil> <nil> <nil> <nil>] var arr3 [2][3]int //二维数组
fmt.Println(arr3) //[[0 0 0] [0 0 0]] // 使用简短的格式
arr4 := [5]int{2, 4, 6, 8, 10}
fmt.Println(arr4) //[2 4 6 8 10] //其他方式,如果长度的位置是... 表示数组长度是根据后面的数据元素个数来计算
arr5 := [...]int{2, 3, 4, 5, 6, 7}
fmt.Println(arr5, len(arr5)) //[2 3 4 5 6 7] 6 // 指定数组的索引来赋值
arr6 := [...]int{5: 10, 7: 23}
//将数组下标为5的元素赋值为10,将数组下标为7的元素赋值为23
//数组长度为8
fmt.Println(arr6, len(arr6)) //[0 0 0 0 0 10 0 23] 8 arr7 := [2][3]int{{1, 2, 3}, {4, 5, 6}}
fmt.Println(arr7) //[[1 2 3] [4 5 6]]
数组访问与数组长度
arr1 := [5]int{2, 4, 6, 8, 10}
fmt.Println(arr1) // [2 4 6 8 10]
fmt.Println("length:", len(arr1)) //length: 5
// arr1[5] = 100 //出错,数组越界
arr1[0] = 99
fmt.Println(arr1) //[99 4 6 8 10] arr2 := [2][3]int{{1, 2, 3}, {4, 5, 6}}
fmt.Println(len(arr2)) //2
fmt.Println(len(arr2[0])) //3
fmt.Println(arr2[1][1]) //5
数组遍历
arr1 := [5]int{2, 4, 6, 8, 10}
for i := 0; i < len(arr1); i++ {
fmt.Println(arr1[i]) //2 4 6 8 10
}
for i, v := range arr1 {
fmt.Print(i, "=>", v) // 0=>2,1=>4,2=>6,3=>8,4=>10
}
// 不需要索引的时候,可以将用_代替i
for _, v := range arr1 {
fmt.Println(v) //2,4,6,8,10
}
数组作为函数参数
数组作为函数作为参数时,如果是给形参传递数组名,那么就是传值操作,传递的是数组的副本,修改副本的内容,并不会影响实参。
要想在函数中对数组的修改作用到实参,可以用数组指针,即->使用指针的形式,将数组的地址传递给函数,并且函数定义时,接收一个指针类型的参数,那么就可以对数组内部进行修改,但是不能修修改数组长度。
package main import "fmt" func Double(arr [5]int) [5]int {
for i := 0; i < 5; i++ {
arr[i] *= 2
}
return arr
} //接收的指针类型,即数组的地址
//注意这里的形参要写成 arr *[5]int 不要写成arr [5]*int
//arr [5]*int表示的是有五个元素的数组,每个元素是一个指针,即5个指针
//arr *[5]int表示的是一个指针,这一个指针指向一个拥有5个元素的数组,每个元素时一个int型变量
func Triple(arr *[5]int) {
for i := 0; i < 5; i++ {
arr[i] *= 3
}
}
func main() {
var arr2 [6]*int //整型指针数组
fmt.Println(arr2) //[<nil> <nil> <nil> <nil> <nil> <nil>]
arr := [5]int{1, 2, 3, 4, 5}
fmt.Println(arr) //[1 2 3 4 5] arr1 := Double(arr)
fmt.Println(arr1) //[2 4 6 8 10]
fmt.Println(arr) //[1 2 3 4 5] Triple(&arr)
fmt.Println(arr) //[3 6 9 12 15]
}
数组类型、数组比较
数组的长度一旦确定,就不能再改变。如果要改变,只能转换为slice,但是用了slice之后,改变的是slice的长度,但是数组长度始终不变。
数组长度不同,那么数组就不是同一个类型,不能相互赋值-->参数传递。
相同类型的数组可以进行比较,这里的类型不只是数组元素的类型,也包括数组的长度都要相同,才能进行比较。
package main
import "fmt"
func Double(arr [5]int) [5]int {
for i := 0; i < 5; i++ {
arr[i] *= 2
}
return arr
} func main() {
arr1 := [5]int{1, 2, 3, 4, 5}
Double(arr1) //正确 形参和实参都是[5]int类型,注意[5]int是一个类型 arr2 := [6]int{1, 2, 3, 4, 5, 6}
Double(arr2) //错误,不能将类型为[6]int的实参,赋值给类型为[5]int的形参
//[5]int和[6]int是两个不同的类型
}
创建切片
var slice []int
//定义一个空切片,注意上面[]中没有指定长度,如果指定长度,就代表是数组了
fmt.Println(slice) //[] slice1 := []int{1, 2, 3, 4, 5}
//创建一个长度和容量为5的切片
fmt.Println(slice1) //[1 2 3 4 5]
fmt.Println(len(slice1), cap(slice1)) //5 5 slice2 := []int{5: 10}
//创建一个长度和容量为6的切片
fmt.Println(slice2) //[0 0 0 0 0 10]
fmt.Println(len(slice2), cap(slice2)) //6 6 //使用make创建切边
//make(type,len,cap),未指定cap是,cap和len相等
slice3 := make([]int, 5, 10)
fmt.Println(slice3, len(slice3), cap(slice3)) //[0 0 0 0 0] 5 10
slice4 := make([]int, 6)
fmt.Println(slice4, len(slice4), cap(slice4)) //[0 0 0 0 0 0] 6 6 // 利用数组创建切片
//[strat:end]左闭右开,start省略时,默认为0;end省略时默认为数组或者切片长度
arr := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice5 := arr[3:]
fmt.Println(slice5) //[3 4 5 6 7 8 9] slice6 := arr[:7]
fmt.Println(slice6) //[0 1 2 3 4 5 6] slice7 := arr[4:8]
fmt.Println(slice7) //[4 5 6 7] slice8 := arr[:]
fmt.Println(slice8) //[0 1 2 3 4 5 6 7 8 9]
通过len函数求的切片长度,判断是否为空。
append函数
使用append函数后,返回的是一个slice类型,不是数组类型
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice) //[1 2 3 4 5] //追加元素
slice = append(slice, 6)
fmt.Println(slice) //[1 2 3 4 5 6] //追加切片
s1 := []int{99, 100}
//注意下面的...表示解构,即,将切片的内容展开后填充到该位置
slice = append(slice, s1...)
fmt.Println(slice)
不能对数组调用append函数,即,append函数的第一个参数必须是slice。
copy函数
copy(destination,resource),复制之后,dest的长度并不会改变,即使复制给他的切片长度远大于它。
//长的slice复制到短的slice
s1 := []int{1, 2, 3, 4, 5}
s2 := []int{10, 20, 30, 40}
copy(s2, s1)
fmt.Println(s2) //[1 2 3 4] //短的slice复制到长的slice
s3 := []int{2, 3, 4}
s4 := []int{9, 8, 7, 6, 5}
copy(s4, s3)
fmt.Println(s4) //[2 3 4 6 5] //相同长度的slice进行复制
s5 := []int{1, 2, 3}
s6 := []int{4, 5, 6}
copy(s6, s5)
fmt.Println(s6) //[1 2 3]
不能使用copy进行数组的复制操作,即,copy的两个参数都必须是slice。
slice作为函数参数
将数组传递给函数之后,在函数中操作的是数组的副本。虽然可以使用数组指针形式传递,但是更通用的是使用slice,使用slice之后,可以通过在函数中修改slice,来达到修改数组的目的。
package main import "fmt" //参数是数组类型
func Double(arr [5]int) {
for i := 0; i < 5; i++ {
arr[i] *= 2
}
} //类型是slice类型
func Triple(slice []int) {
for i := 0; i < len(slice); i++ {
slice[i] *= 3
}
}
func main() {
arr := [5]int{1, 2, 3, 4, 5}
Double(arr)
fmt.Println(arr) //[1 2 3 4 5] //数组转换为切片
slice := arr[:]
Triple(slice)
fmt.Println(arr) //[3 6 9 12 15]
}
创建map
//定义空的映射,默认值为nil
var m1 map[int]string
fmt.Println(m1) //map[]
//再进行初始化
m1 = map[int]string{
1: "hello",
8: "world", //注意这种写法,末尾的逗号不可省
}
fmt.Println(m1) //map[1:hello 8:world] //使用make创建映射,注意此时最多只用两个参数,
//一个是map的映射类型,一个map的容量,容量可以省略
//但是没有len这一个参数,即不能指定长度这一项
m2 := make(map[int]string, 100)
fmt.Println(m2, len(m2)) m3 := make(map[string][]string)
m3["server"] = []string{"apache", "nginx"}
m3["language"] = []string{"php", "golang", "python"}
fmt.Println(m3) //map[server:[apache nginx] language:[php golang python]] //创建映射,同时初始化,此时不需要使用make
m4 := map[int]string{1: "demo", 2: "test"}
fmt.Println(m4) //map[1:demo 2:test]
删除map元素
//字符串映射到string类型的切片
m1 := map[string][]string{
"server": []string{"apache", "nginx"},
"language": []string{"php", "python", "golang"},
}
fmt.Println(m1) //map[server:[apache nginx] language:[php python golang]] //删除没有的key,不报错
delete(m1, "client")
fmt.Println(m1) //map[server:[apache nginx] language:[php python golang]] delete(m1, "server")
fmt.Println(m1) //map[language:[php python golang]]
查找map元素
//字符串映射到string类型的切片
m1 := map[string][]string{
"server": []string{"apache", "nginx"},
"language": []string{"php", "python", "golang"},
}
fmt.Println(m1) //map[server:[apache nginx] language:[php python golang]] //访问一个不存在的元素,不会报错,返回类型零值
fmt.Println(m1["client"]) //[] v, exists := m1["client"]
fmt.Println(v, exists) //[] false v, exists = m1["server"]
fmt.Println(v, exists) //[apache nginx] true
遍历map
//字符串映射到string类型的切片
m1 := map[string][]string{
"server": []string{"apache", "nginx"},
"language": []string{"php", "python", "golang"},
}
for key, value := range m1 {
fmt.Println(key, "=>", value)
}
//server => [apache nginx]
//language => [php python golang]
映射是无序的,所以遍历多次的结果,元素的顺序不一定完全相同
map注意事项
1、map之间不能进行比较,但是可以和nil进行比较
2、不能对map取地址,因为map本就是引用类型
var m0 map[int]string
fmt.Println(m0 == nil) //true var m1 map[int]string
fmt.Println(m0 == m1) //不能进行比较,会报错 m2 := map[int]string{1: "one", 2: "two"}
fmt.Println(m2 == nil) //false
map作为函数参数
package main import "fmt" //接受一个map
func Show(m map[int]string) {
m[1] = "three"
m[3] = "four"
}
func main() {
m1 := map[int]string{
1: "one",
2: "two",
}
fmt.Println(m1) //map[1:one 2:two] Show(m1)
fmt.Println(m1) //map[3:four 1:three 2:two]
}
将map作为函数的参数,在函数中修改map,会直接影响到实参,因为map是引用类型。
Golang 数组、切片、映射的更多相关文章
- Golang 数组 切片 字典 基本知识点
数组 数组的声明 var arrayName [arraySize]dataType eg: var array1 [5]int 在声明数组时,必须指定数组名,数组长度和数组元素的类型. 数组的初始化 ...
- GoLang数组切片
1. 数组1.1 如何定义数组同java数组一样,数组是一组内存连续且类型相同的数据组成 //不初始化初始值默认为0 var arr1 = [5]int{} var arr2 = [5]int{1,2 ...
- [golang note] 数组切片
数组 √ golang数组包含的每个数据称为数组元素(element),数组包含的元素个数被称为数组长度(length). √ golang数组的长度在定义后不可更改,并且在声明时可以是一个常量或常量 ...
- golang中不定参数与数组切片的区别
package main import "fmt" func main() { myfunc1(, , , ) //传递不定数量的参数 myfunc2([], , , }) //传 ...
- Go语言学习之4 递归&闭包&数组切片&map&锁
主要内容: 1. 内置函数.递归函数.闭包2. 数组与切片3. map数据结构4. package介绍 5. 排序相关 1. 内置函数.递归函数.闭包 1)内置函数 (1). close:主要用来关闭 ...
- 窥探Swift之数组安全索引与数组切片
今天是元宵节,祝大家元宵节快乐!在Swift中的数组和字典中下标是非常常见的,数组可以通过索引下标进行元素的查询,字典可以通过键下标来获取相应的值.在使用数组时,一个常见的致命错误就是数组越界.如果在 ...
- go语言 类型:数组切片
初看起来,数组切片就像一个指向数组的指针,实际上它拥有自己的数据结构,而不仅仅是个指针.数组切片的数据结构可以抽象为以下3个变量: 1.一个指向原生数组的指针: 2.数组切片中的元素个数: 3.数组切 ...
- go语言中的数组切片:特立独行的可变数组
go语言中的数组切片:特立独行的可变数组 初看go语言中的slice,觉得是可变数组的一种很不错的实现,直接在语言语法的层面支持,操作方面比起java中的ArrayList方便了许多.但是在使用了一段 ...
- GO中的数组切片
GO中的数组切片可以看做是功能更强大的数组,在append数据时,可以自动调整内存大小以适应数据实际大小,有些类似于C#中的List<T>. GO 中数组切片的“容量”与实际储存的大小可以 ...
随机推荐
- Properties集合_修改配置信息
集合中的数据来自于一个文件 注意:必须要保证该文件中的数据是键值对. 需要使用到读取流 使用load()方法读取已有文件中的数据,存储到Properties集合中 public class Pro ...
- ROS 订阅图像节点
博客 http://blog.csdn.net/github_30605157/article/details/50990493 参考ROS原网站 http://wiki.ros.org/image_ ...
- Linux 之 rsyslog 系统日志转发
一.rsyslog 介绍 ryslog 是一个快速处理收集系统日志的程序,提供了高性能.安全功能和模块化设计.rsyslog 是syslog 的升级版,它将多种来源输入输出转换结果到目的地,据官网介绍 ...
- sed插入,替换指定行的特定字符串,删除指定行首的#
sed -i '$a service snmpd start' /etc/rc.local sed -i "41s:public:mykey:g" /etc/snmp/snmpd. ...
- Spring与SpringMVC的区别
Spring是IOC和AOP的容器框架,SpringMVC是基于Spring功能之上添加的Web框架,想用SpringMVC必须先依赖Spring. 简单点的话可以将SpringMVC类比于Strut ...
- 理解WebSocket心跳及重连机制(五)
理解WebSocket心跳及重连机制 在使用websocket的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发onclose的事件.这样会有:服务器会继续向客户端发送多余的 ...
- C++ assert断言
assert断言通常用于调试,用法如下: assert(expr); // 当expr==0时,系统会调用abort来终止程序运行 调试完成后,可以在include <assert.h>之 ...
- SQL 行转列 列转行 PIVOT UNPIVOT
1.基础表 2.行转列,注意ISNULL函数的使用,在总成绩的统计中,ISNULL(-,0) 有必要使用 3.列转行,对列语文.数学.英语.政治,进行列转行,转为了2列,score scname 这两 ...
- [01] Why Spring
1.何为框架 简单来说,框架就是制定了一套规范或者规则(思想),让程序员在该规范或规则下进行工作.如上图修楼房,在有框架的情况下,修建工作才高效且有条不紊.楼层钢架规定了大楼的结构,工人按架构添砖放瓦 ...
- BZOJ1816 CQOI2010 扑克牌 贪心
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1816 题意:有$N$堆牌,第$i$堆牌有$c_i$张牌,还有$M$张$joker$,每 ...