【启程Golang之旅】掌握Go语言数组基础概念与实际应用

news2024/11/15 15:58:08

欢迎来到Golang的世界!在当今快节奏的软件开发领域,选择一种高效、简洁的编程语言至关重要。而在这方面,Golang(又称Go)无疑是一个备受瞩目的选择。在本文中,带领您探索Golang的世界,一步步地了解这门语言的基础知识和实用技巧。

目录

初识数组

二维数组

slice切片

map映射


初识数组

        在Go语言中,数组是一种固定长度的、包含相同类型元素的序列。数组的长度是类型的一部分,因此[5]int和[10]int是两种不同的类型。数组在Go中是值类型,这意味着当你传递一个数组到函数或将其赋值给另一个变量时,实际上是在复制整个数组的内容。

在Go语言中数组的内存分配是静态的,并且是在编译时确定的。由于数组的长度是类型的一部分,所以不同长度的数组在内存中的表示和占用是不同的。以下是关于Go语言中数组内存分析的代码示例:

package main
import "fmt"
func main() {
	// 声明数组
	var arr [3]int16
	// 获取数组长度
	fmt.Println(len(arr)) // 3
	// 打印数组
	fmt.Println(arr) // [0 0 0]
	// 证明arr中存储的是地址值
	fmt.Printf("arr的地址为:%p \n", &arr) // arr的地址为:0xc0000100b0
	// 第一个空间地址
	fmt.Printf("arr[0]的地址为:%p \n", &arr[0]) // arr[0]的地址为:0xc0000100b0
	// 第二个空间地址
	fmt.Printf("arr[1]的地址为:%p \n", &arr[1]) // arr[1]的地址为:0xc0000100b2
	// 第三个空间地址
	fmt.Printf("arr[2]的地址为:%p \n", &arr[2]) // arr[2]的地址为:0xc0000100b4
}

因为int占两个字节,所以地址值之间间隔为2,如下是图例解释:

接下来我们通过用户终端输入的方式,将数据存入数组当中,然后遍历数组,将数据打印出来:

package main
import "fmt"
func main() {
	// 定义数组
	var scores [5]int
	// 将成绩存入数组
	for i := 0; i < len(scores); i++ {
		fmt.Printf("请录入第%d个学生的成绩", i+1)
		fmt.Scanln(&scores[i])
	}
	// 展示一下录入学生的成绩:(对数组进行遍历)
	for i := 0; i < len(scores); i++ {
		fmt.Printf("第%d个学生的成绩为:%d \n", i, scores[i])
	}
	// 求和
	sum := 0
	for i := 0; i < len(scores); i++ {
		sum += scores[i]
	}
	// 平均数
	avg := sum / len(scores)
	// 输出
	fmt.Printf("成绩的总和为:%v, 成绩的平均数为:%v", sum, avg)
}

最终呈现的效果如下所示:

当然这里也可以采用for range的方式,for range结构是go语言中特有的一种迭代结构,在许多情况下都非常有用,for range可以遍历数组、切片、字符串、map及通道,示例代码如下,最终也能得到上面图片的结果:

func main() {
	// 定义数组
	var scores [5]int
	// 将成绩存入数组
	for i := 0; i < len(scores); i++ {
		fmt.Printf("请录入第%d个学生的成绩", i+1)
		fmt.Scanln(&scores[i])
	}
	// 展示一下录入学生的成绩:(对数组进行遍历) for range方式
	for key, value := range scores {
		fmt.Printf("第%d个学生的成绩为:%d \n", key+1, value)
	}
}

数组可以有多种书写方式,如下可以看到我们数组的书写方式:

package main
import "fmt"
func main() {
	// 数组的几种书写方式
	// var scores [5]int = [5]int{94, 98, 89, 80, 90} // 基本写法
	// var scores = [5]int{94, 98, 89, 80, 90} // 省略类型和长度
	//var scores = [...]int{2: 66, 0: 33, 1: 99, 3: 88} // 确定数组下标对应的数值
	scores := []int{94, 98, 89, 80, 90} // 使用切片(slice)语法(这在Go中更为常见)
	sum := 0
	for i := 0; i < len(scores); i++ {
		// 求得成绩的总值
		sum += scores[i]
	}
	// 平均数
	avg := sum / len(scores)
	// 输出
	fmt.Printf("成绩的总和:%v, 成绩的平均数为:%v\n", sum, avg)
}

在go语言中,关于数组还有以下注意事项,这里做一个简单的概述:

长度属于类型的一部分:

func main() {
	// 定义一个数组
	var arr1 = [3]int{1, 2, 3}
	fmt.Printf("数组的类型为:%T", arr1) // [3]int

	var arr2 = [6]int{3, 4, 5, 6, 7, 8}
	fmt.Printf("数组的类型为:%T", arr2) // [6]int
}

数组属于值类型,在默认情况下是值传递,因此会进行值拷贝,如下图所示我对数组的值进行修改是修改了arr的值,并不是arr3的:

如想在其它函数中去修改原来的数组,可以使用引用传递(指针方式):

package main
import "fmt"
func test(arr *[3]int) {
	(*arr)[0] = 7
}

func main() {
	var arr3 = [3]int{3, 6, 9}
	test(&arr3)       // 传入arr3数组的地址
	fmt.Println(arr3) // [7 6 9]
}

二维数组

在Go语言中,二维数组(也称为矩阵)是一个数组,其中每个元素都是另一个数组。这意味着你可以有两个维度来索引数据:第一个维度表示行,第二个维度表示列。示例代码如下:

func main() {
	var arr1 [2][3]int = [2][3]int{{1, 2, 3}, {4, 5, 6}}
	fmt.Println(arr1) // [[1 2 3] [4 5 6]]
}

在下面的例子中,array2D 是一个5行3列的二维整型数组,这里可以通过array2D[row][column]的方式来访问或修改数组中的元素:

func main() {
	// 声明一个5行3列的二维整型数组
	var array2D [5][3]int
	// 初始化时直接赋值
	array2D = [5][3]int{
		{1, 2, 3},
		{4, 5, 6},
		{7, 8, 9},
		{10, 11, 12},
		{13, 14, 15},
	}
	// 访问二维数组中的元素
	fmt.Println(array2D[2][1]) // 输出: 8
}

如果想对二维数组进行遍历的话,需要用到双层for循环,这里进行一个简单的示例:

package main
import "fmt"
func main() {
	// 定义二维数组
	var arr = [3][3]int{{1, 4, 7}, {2, 5, 8}, {3, 6, 9}}
	fmt.Println(arr)
	fmt.Println("---------------")
	// 方式1:普通for循环
	for i := 0; i < len(arr); i++ {
		for j := 0; j < len(arr[i]); j++ {
			fmt.Print(arr[i][j], "\t")
		}
		fmt.Println()
	}
	// 方式2:for range循环
	for key, value := range arr {
		for k, v := range value {
			fmt.Printf("arr[%v][%v] = %v \t", key, k, v)
		}
		fmt.Println()
	}
}

最终达到的效果如下所示:

slice切片

在Go语言中,切片(slice)是对数组的一个连续片段的引用,它本身并不包含数组的数据,而是包含了对底层数组的引用、长度以及容量。切片提供了一种灵活、方便且高效的方式来操作数组的一个子集,是一种建立在数组类型之上的抽象,它构建在数组之上并且提供更强大的能力和便捷,如下代码给出切片的示例:

package main
import "fmt"
func main() {
	// 定义数组
	var intarr [6]int = [6]int{3, 6, 7, 1, 2, 3}
	// 定义切片 slice [1:3]表示切出的一段片段,索引从1开始,到3结束
	slice := intarr[1:3]
	// 输出数组
	fmt.Println("intarr: ", intarr) // intarr:  [3 6 7 1 2 3]
	// 输出切片
	fmt.Println("slice: ", slice) // slice:  [6 7]
	// 切片元素个数
	fmt.Println("slice的元素个数: ", len(slice)) // slice的元素个数:  2
	// 获取切片的容量,容量可以动态变化
	fmt.Println("slice的容量: ", cap(slice)) // slice的容量:  5
}

切片由3个字段的数据结构组成:指向底层数组的指针、切片的长度、切片的容量

切片的创建:在Go语言中,make 是一个内置函数,用于动态地分配并初始化对象,这些对象包括切片(slices)、映射(maps)和通道(channels)。特别是当我们谈论切片时,make 是创建它们的主要方式,使用 make 创建切片的基本语法如下所示:

slice := make([]T, length, capacity)

这里通过如下代码进行简单示例,在下面的示例中,我们创建了一个整数类型的切片 slice,其长度为 3,容量为 5。这意味着切片当前可以存储 3 个整数,但底层数组的大小为 5,因此将来可以在不重新分配内存的情况下向切片添加最多 2 个额外的整数。

func main() {
	// 定义切片:make函数的三个参数:1、切片类型 2、切片长度 3、切片容量
	slice := make([]int, 3, 5)
	fmt.Println(slice)               // [0 0 0]
	fmt.Println("切片的长度", len(slice)) // 切片的长度 3
	fmt.Println("切片的容量", cap(slice)) // 切片的容量 5
}

make底层创建一个数组,对外不可见,所以不可以直接操作这个数组,要通过slice去间接的访问各个元素,不可以直接对数组进行维护/操作。

切片的遍历:对切片的遍历可以采用如下的方式进行:

func main() {
	// 定义切片:make函数的三个参数:1、切片类型 2、切片长度 3、切片容量
	slice := make([]int, 4, 20)
	slice[0] = 66
	slice[1] = 77
	slice[2] = 88
	slice[3] = 99
	// 方式1:普通for循环,遍历切片
	for i := 0; i < len(slice); i++ {
		fmt.Printf("slice[%v] = %v \t", i, slice[i])
	}
	fmt.Println("\n------------------------")
	// 方式2:for range循环,遍历切片
	for index, value := range slice {
		fmt.Printf("slice[%v] = %v \t", index, value)
	}
}

最终呈现的效果如下所示:

切片的注意事项

1)切片定义后不可以直接使用,需要让其引用到一个数组,或者make一个空间供切片来使用

2)切片使用不能越界

3)切片的简写方式

var slice = arr[0:end] ----》 var slice = arr[:end]

var slice = arr[start:len(arr)] ----》 var slice = arr[start:]

var slice = arr[0:len(arr)] ----》 var slice = arr[:]

4)切片可以继续切片

5)切片可以动态增长

func main() {
	// 定义数组
	var intarr [6]int = [6]int{1, 4, 7, 3, 6, 9}
	// 定义切片
	var slice []int = intarr[1:4] // 4 7 3
	fmt.Println(len(slice))       // 3
	slice2 := append(slice, 88, 50)
	fmt.Println(slice2) // [4 7 3 88 50]
	fmt.Println(slice)  // [4 7 3]
	/* 底层原理
	   1.底层追加元素的时候对底层数组扩容,老数组扩容为新数组
	   2.创建一个新数组,将老数组中的 4,7,3 拷贝到新数组中,在新数组中追加 88,50
	   3.slice2底层数组的指向 指向的是新数组
	   4.往往我们在使用追加的时候其实想要做的效果是给slice追加元素,而不是给底层数组追加元素
	*/
	slice = append(slice, 10)
	fmt.Println(slice) // [4 7 3 10]
	// 底层的新数组不能直接维护,因为slice2底层数组的地址已经变了,所以我们需要重新创建一个新的切片,通过切片间接操作
	slice3 := []int{99, 44}
	slice = append(slice, slice3...)
	fmt.Println(slice) // [4 7 3 10 99 44]
}

6)切片的拷贝

func main() {
	// 定义数组
	var a []int = []int{1, 4, 7, 3, 6, 9}
	// 再定义一个切片
	var b []int = make([]int, 10)
	// 拷贝
	copy(b, a)     // 将a中的值拷贝到b中
	fmt.Println(b) // [1 4 7 3 6 9 0 0 0 0]
}

map映射

在Go语言中,map 是一种内置的数据结构,用于存储键值对(key-value pairs)的集合。map 提供了根据键来存储、检索和删除值的能力,使得在Go中处理关联数据变得非常方便,接下来通过如下代码示例进行演示:

func main() {
	// 定义map变量
	/*
		map: 这表示我们正在声明一个 map 类型的变量
		[int]string: 这部分定义了 map 的键和值的类型
		具体来说,int 是键的类型,而 string 是值的类型
		这意味着你可以将整数用作键,并将字符串作为与这些键相关联的值存储在 map 中
	*/
	var a map[int]string
	// 只声明map内存是没有分配空间的,需要使用make函数初始化分配空间
	a = make(map[int]string, 10) // map可以存放10个键值对,10可以不传,默认会分配一个起始大小
	// 初始化map
	a[3] = "one"
	a[1] = "two"
	a[2] = "three"
	// 输出集合
	fmt.Println(a) // map[1:one 2:two 3:three]
}

注意:map集合在使用前一定要make;map的key是按照从小到大排序;key值不能重复,如果重复后一个value会对前一个进行覆盖,value是可以重复的;make函数的第二个参数size可以省略,默认就分配一个内存

map的创建方式可以通过如下的操作进行:

func main() {
	// map的创建方式
	// 方式1
	a := make(map[int]string)
	a[2020] = "张三"
	a[2019] = "李四"
	fmt.Println(a) // map[2019:李四 2020:张三]
	// 方式2
	b := map[int]string{
		2019: "张三",
		2020: "李四",
	}
	b[2018] = "王五"
	fmt.Println(b) // map[2018:王五 2019:张三 2020:李四]
}

当然我们也可以通过map对数值进行增删改查的操作,具体如下:

增加和更新操作:map["key"]= value 一》如果key还没有,就是增加,如果key存在就是修改。

func main() {
	a := make(map[int]string)
	// 增加操作
	a[2020] = "张三"
	a[2019] = "李四"
	// 修改操作
	a[2020] = "张三!!!"
	fmt.Println(a) // map[2019:李四 2020:张三!!!]
}

删除操作:delete(map,“key"),delete是一个内置函数,如果key存在,就删除该key-value,如果k的y不存在,不操作,但是也不会报错。

func main() {
	a := make(map[int]string)
	// 增加操作
	a[2020] = "张三"
	a[2019] = "李四"
	// 删除操作
	delete(a, 2019)
	fmt.Println(a) // map[2020:张三]
}

清空操作:如果我们要删除map的所有key,没有一个专门的方法一次删除,可以遍历一下key,逐个删除;或者map=make(),make一个新的,让原来的成为垃圾,被gc回收。

查找操作:value ,bool = map[key];value为返回的value,bool为是否返回,要么true要么false。

func main() {
	a := make(map[int]string)
	// 增加操作
	a[2020] = "张三"
	a[2019] = "李四"
	// 查找操作
	value, flag := a[2019]
	if flag {
		fmt.Println(value) // 李四
	} else {
		fmt.Println("查找不到")
	}
	fmt.Println(a) // map[2020:张三]
}

当然map还有一些其他的操作,这里进行一个简单的演示:

package main
import "fmt"
func main() {
	a := make(map[int]string)
	a[2020] = "张三"
	a[2019] = "李四"
	a[2018] = "王五"
	// 获取长度
	fmt.Println(len(a))
	// 遍历
	for k, v := range a {
		fmt.Printf("key为:%v value为 %v \n", k, v)
	}
	// 上操作
	b := make(map[string]map[int]string) // 嵌套map
	// 赋值
	b["班级1"] = make(map[int]string)
	b["班级1"][2020] = "张三"
	b["班级1"][2019] = "李四"
	b["班级1"][2018] = "王五"
	b["班级2"] = make(map[int]string)
	b["班级2"][2019] = "张三1"
	b["班级2"][2018] = "李四1"
	b["班级2"][2017] = "王五1"
	// 遍历
	for k, v := range b {
		fmt.Println(k)
		for k1, v1 := range v {
			fmt.Printf("key为:%v value为 %v \n", k1, v1)
		}
	}
}

最终呈现的效果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1706085.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何搭建雾锁王国多人联机服务器,搭建教程分享

雾锁王国&#xff08;Enshrouded&#xff09;是一款融合了生存、制作以及动作RPG战斗的游戏&#xff0c;2024年1月24日在Steam平台以抢先体验形式发售&#xff0c;支持中文。游戏背景设定在一个基于体素构筑的辽阔大陆上。玩家将在这个开放世界中自由选择前进的方向&#xff0c…

你知道【无犯罪记录证明】怎么开具吗?

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 有些事情没有经历过&#xff0c;就不会知道&#xff0c;经历过一次也就晓得了。 所谓见多识广&#xff0c;很多就是见过或者听说过&#xff0c;像刘姥姥进大观园&#xff0c;很多事物是没见过&#xff0c;才会闹出很多…

升级 JDK17 一个不可拒绝的理由!

插&#xff1a; AI时代&#xff0c;程序员或多或少要了解些人工智能&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家(前言 – 人工智能教程 ) 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家…

Java入门-java的集合框架

集合概念 集合&#xff0c;有时也称作容器(Container), 是对象的持有者&#xff0c;它们可以有助于高效访问的方式存储的组织对象。以生活中的案例为例&#xff1a; 集合就像装衣服的柜子&#xff0c;衣服就是集合中的元素。 集合框架图 Collection中每次操作的都是一个对象&a…

【Python编程】JetBrains PyCharm IDE专业版 学生优惠过期怎么办?【妥协的解决方法】

写在前面 笔者临近硕士毕业&#xff0c;用了7年左右的JB学生包终于过期了&#xff08;依依不舍&#xff09;。。。之前用得顺手的PyCharm&#xff0c;WebStorm&#xff0c;CLion&#xff08;专业版&#xff09;等等IDE都暂时告别了。笔者无意以个人身份购买许可证&#xff0c;…

android studio 导入github里的项目后提示:Add Configuration

原文链接&#xff1a;https://blog.csdn.net/weixin_45677723/article/details/125940912 从github上面clone项目&#xff0c;出现下图问题&#xff1a; 解决问题&#xff1a; 我这个的情况是因为多文件嵌套了&#xff0c;我用Android Studio打开的是A文件&#xff0c;而B项…

oracle adg dup 一拖一拖一(一主两备)(dup)

oracle adg dup 一拖一拖一&#xff08;一主两备&#xff09; 1.配置Public IP ora1 nmcli connection modify ens33 ipv4.addresses 192.168.134.249/24 ipv4.gateway 192.168.134.2 ipv4.method manual autoconnect yes nmcli connection up ens33 nmcli connection show o…

金蝶云星空与旺店通·企业版对接集成采购入库查询打通创建采购入库单

金蝶云星空与旺店通企业版对接集成采购入库查询打通创建采购入库单 数据源系统:金蝶云星空 金蝶K/3Cloud&#xff08;金蝶云星空&#xff09;是移动互联网时代的新型ERP&#xff0c;是基于WEB2.0与云技术的新时代企业管理服务平台。金蝶K/3Cloud围绕着“生态、人人、体验”&…

嵌入式学习记录5.18(多点通信)

一、套接字属性设置相关函数 #include <sys/types.h> /* See NOTES */#include <sys/socket.h>int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname,const void *op…

Python批量docx或doc文档转换pdf

说明&#xff1a; 1、因为项目需要&#xff0c;需要手动将十几个word文档转换成pdf文档 2、python请安装3.9.0以上&#xff0c;否则一些依赖库无法正常用 #! /usr/bin/python3 # -*- coding: utf-8 -*-import os import comtypes.client# 批量将docx文件转换pdf文件 def docx_t…

1109 擅长C(测试点0,1,2,3)

当你被面试官要求用 C 写一个“Hello World”时&#xff0c;有本事像下图显示的那样写一个出来吗&#xff1f; ..C.. .C.C. C...C CCCCC C...C C...C C...C CCCC. C...C C...C CCCC. C...C C...C CCCC. .CCC. C...C C.... C.... C.... C...C .CCC. CCCC. C...C C...C C...C C…

【马蹄集】— 百度之星 2023

BD202301公园 可以先 b f s bfs bfs统计一下 t , f t,f t,f到达每个点的距离&#xff0c;还有 n n n到达其他点的距离即其他点到达 n n n的距离 然后枚举每个点 直接计算得到最小值即可 注意特判有人无法到达 n n n的情况 code: #include<bits/stdc.h> #define endl \n…

品牌做电商控价的原因

品牌控价确实是一项至关重要的任务&#xff0c;它关乎着品牌形象、市场定位以及长期发展的稳定性。在电商平台上&#xff0c;价格的公开性和透明度使得消费者、经销商和其他渠道参与方都能够轻易地进行价格比较。因此&#xff0c;品牌方必须对电商渠道的价格进行严格的管控&…

电商API接口助力直播带货选品||助力电商平台搭建选品

如今&#xff0c;直播带货如火如荼。直播带货的核心是卖货、品牌盈利&#xff0c;那想要带货效果更好&#xff0c;选品及定价是最关键的环节。 事实上&#xff0c;品牌企业可以直接使用API接口工具来辅助自身选品及定价&#xff0c;这主要是因为比价工具在直播带货选品环节能起…

因智而兴 向“新”而行 | 软通动力携子公司鸿湖万联亮相数字中国建设峰会·智算云生态大会

5月23日至27日&#xff0c;第七届数字中国建设峰会在福州盛大召开。作为峰会的重要组成部分&#xff0c;由中国电信、中国电科、中国电子联合主办的第三届智算云生态大会同步召开。此次大会以“国云注智 聚力向新”为主题&#xff0c;深入探讨了智算云、人工智能、数据要素、量…

干货!渗透测试入门教程!(建议收藏)

渗透测试是指从内网、外网等网络环境中&#xff0c;利用各种手段对某个特定网络进行模拟攻击&#xff0c;目的是为了寻找可能被利用的漏洞&#xff0c;是企业中重要的一环、 虽然大多数人在学习后都能快速上手&#xff0c;但渗透测试还是有一定的门槛&#xff0c;今天就给大家…

电脑重要文件如何加密保护?教你两种方法

加密是保护电脑重要文件的常见方法&#xff0c;可以有效避免文件数据泄露。那么&#xff0c;电脑重要文件该如何加密保护呢&#xff1f;下面小编就来教你两种方法&#xff0c;帮助你解决文件安全问题。 超级加密3000 超级加密3000是一款专业的电脑数据加密软件&#xff0c;可以…

自定义CSS属性(@property)解决自定义CSS变量无法实现过渡效果的问题

且看下面的代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>demot</title&g…

幼儿园老师投稿渠道

幼儿园老师投稿通常指的是教师为了分享自己的教学经验、教育活动设计、儿童发展研究等内容&#xff0c;向专业杂志、教育平台或在线论坛提交文章或资料的过程。以下是一些关于幼儿园老师投稿的步骤和建议&#xff1a; 一、准备工作 选择合适的平台 研究不同平台的读者群体&a…

大连瓦房店市科工局副局长乔宽一行调研蓝卓

日前&#xff0c;瓦房店市科技和工业信息化局副局长乔宽、副局长国海军、轴承协会秘书长高钧一行莅临蓝卓调研&#xff0c;学习浙江数字经济发展路径&#xff0c;考察蓝卓数字化服务能力。蓝卓副总经理陈挺、装备汽配军团总监陈伟亮、数字化咨询总监周立斌、大连区域方案经理龚…