【go 】数组的多种初始化方式与操作

在 Go 语言中,数组是一种固定长度的数据结构,用于存储相同类型的元素。以下是 Go 中数组的多种初始化方式,结合搜索结果整理如下:

(一)使用 var 关键字声明并初始化数组

使用 var 关键字声明数组时,可以指定数组的长度,数组的元素会被自动初始化为对应类型的零值。例如:

var arr [5]int // 声明一个长度为5的整型数组,元素默认初始化为0

这种方式适用于需要明确数组长度且元素初始值为零值的场景。

(二)声明时直接初始化数组

在声明数组的同时,可以直接指定数组的元素值。例如:

var arr = [5]int{1, 2, 3, 4, 5} // 声明并初始化一个长度为5的整型数组

这种方式适用于已知数组元素值的场景。

(三)使用短变量声明初始化数组

通过短变量声明 := 可以更简洁地初始化数组。例如:

arr := [5]int{1, 2, 3, 4, 5} // 使用短变量声明并初始化数组

这种方式适用于函数内部或需要快速声明和初始化数组的场景。

(四)部分初始化数组

在初始化数组时,可以只指定部分元素的值,未指定的元素会被初始化为零值。例如:

arr := [5]int{1, 2} // 初始化前两个元素为1和2,其余为0

这种方式适用于需要部分元素初始化的场景。

(五)使用 ... 自动推断数组长度

在初始化数组时,可以使用 ... 让编译器根据初始化值的个数自动推断数组长度。例如:

arr := [...]int{1, 2, 3, 4, 5} // 自动推断数组长度为5

这种方式适用于数组长度由初始化值决定的场景。

(六)指定索引初始化数组

在初始化数组时,可以指定某些索引位置的值,未指定的索引位置会被初始化为零值。例如:

arr := [5]int{1: 10, 3: 30} // 初始化索引1为10,索引3为30,其余为0

这种方式适用于需要指定特定索引位置值的场景。

总结

Go 语言提供了多种数组的初始化方式,包括使用 var 关键字、短变量声明、部分初始化、自动推断长度以及指定索引初始化等。这些方式可以根据实际需求灵活选择,以满足不同场景下的使用需求。


数组元素操作

在 Go 语言中,数组是一种固定长度同类型的集合。我们可以对数组元素进行访问、修改、遍历、拷贝等操作。下面详细介绍数组元素的常见操作方法。

一、声明和初始化数组

1. 声明数组

var arr [5]int // 声明一个长度为 5 的 int 数组,默认值为 0

2. 初始化数组

arr := [3]int{1, 2, 3} // 声明并初始化

也可以让编译器推断长度:

arr := [...]int{1, 2, 3, 4} // 长度自动推断为 4

二、访问数组元素

通过索引访问数组元素,索引从 0 开始:

arr := [3]int{10, 20, 30}
fmt.Println(arr[0]) // 输出 10
fmt.Println(arr[1]) // 输出 20

⚠️ 注意:索引超出范围会导致 panic:

fmt.Println(arr[3]) // panic: index out of range [3] with length 3

三、修改数组元素

通过索引直接赋值即可修改元素:

arr := [3]int{10, 20, 30}
arr[1] = 99
fmt.Println(arr) // 输出 [10 99 30]

四、遍历数组元素

1. 使用 for 循环

for i := 0; i < len(arr); i++ {fmt.Println(arr[i])
}

2. 使用 range(推荐)

for i, v := range arr {fmt.Printf("index: %d, value: %d\n", i, v)
}

五、数组长度

使用 len() 获取数组长度:

arr := [3]int{1, 2, 3}
fmt.Println(len(arr)) // 输出 3

六、数组拷贝

Go 数组是值类型,赋值时会完整拷贝整个数组:

a := [3]int{1, 2, 3}
b := a
b[0] = 99
fmt.Println(a) // [1 2 3]
fmt.Println(b) // [99 2 3]

七、多维数组

Go 支持多维数组,例如二维数组:

var matrix [2][3]int
matrix[0] = [3]int{1, 2, 3}
matrix[1] = [3]int{4, 5, 6}
fmt.Println(matrix)
// 输出: [[1 2 3] [4 5 6]]

八、数组 vs 切片(slice)

特性数组(Array)切片(Slice)
长度固定动态变化
传递方式值拷贝引用传递
声明方式[n]T[]T
常用场景已知固定长度数据动态长度、灵活操作

九、示例代码汇总

package main
import "fmt"
func main() {// 声明并初始化arr := [3]int{10, 20, 30}// 访问元素fmt.Println(arr[0]) // 10// 修改元素arr[1] = 99fmt.Println(arr) // [10 99 30]// 遍历for i, v := range arr {fmt.Printf("index: %d, value: %d\n", i, v)}// 数组拷贝b := arrb[0] = 100fmt.Println(arr) // [10 99 30]fmt.Println(b)   // [100 99 30]
}

十、总结

  • Go 数组是固定长度、同类型的集合。
  • 通过索引访问和修改元素。
  • 使用 range 遍历数组更方便。
  • 数组是值类型,赋值或传参时拷贝整个数组。
  • 如需动态长度,应使用切片(slice)。

存储不同类型的元素

在 Go 语言中,数组(array)只能存储相同类型的元素。这是 Go 类型系统的一个基本特性,它要求数组中的所有元素必须是同一类型,以确保类型安全和内存布局的一致性。


一、为什么数组不能存储不同类型的元素?

Go 是静态类型语言,数组的类型由其元素类型长度共同决定。例如:

var arr [3]int // 这是一个包含 3 个 int 类型元素的数组

如果你尝试将不同类型的值放入数组,比如:

arr[0] = 10
arr[1] = "hello" // 编译错误:cannot use "hello" (type untyped string) as type int

就会在编译时报错,因为类型不匹配。


二、如何实现存储不同类型的数据?

虽然 Go 数组不能存储不同类型,但你可以通过以下方式模拟存储多种类型的数据:

1. 使用 interface{}(空接口)

interface{} 是 Go 中的万能类型,可以表示任何类型。你可以声明一个 []interface{} 类型的切片(slice)来存储不同类型的值:

var data []interface{} = []interface{}{42,"hello",3.14,true,
}
for _, v := range data {fmt.Println(v)
}

注意:使用 interface{} 会失去类型安全,访问时需要类型断言(type assertion):

val := data[1].(string) // 断言为 string 类型
fmt.Println(val)
2. 使用结构体(struct)

如果你希望更结构化地存储不同类型的数据,可以定义一个结构体,将不同类型作为字段:

type Item struct {ID    intName  stringPrice float64
}
items := [2]Item{{1, "Apple", 2.5},{2, "Banana", 1.8},
}
3. 使用联合体(C 风格)—— 不推荐

Go 没有像 C 语言那样的联合体(union),也不鼓励使用 unsafe 包来模拟,因为会破坏类型安全。

三、数组 vs 切片 vs 接口切片

类型是否可存多种类型特点
[n]T❌ 否固定长度,类型必须一致
[]T❌ 否动态长度,类型必须一致
[]interface{}✅ 是动态长度,可存任意类型

四、总结

  • Go 数组不能存储不同类型,必须保持元素类型一致。
  • 若需存储多种类型,推荐使用 []interface{} 或自定义结构体。
  • 使用 interface{} 时要注意类型断言,避免运行时错误。

使用数组作为函数参数示例

在 Go 语言中,数组可以作为函数参数传递,但由于数组是值类型,这意味着传递时会复制整个数组,而不是传递引用。下面我们详细讲解如何使用数组作为函数参数,包括传值、传指针、以及一些注意事项。

一、传值方式(默认行为)

1. 基本语法

当数组作为函数参数时,默认是值传递,即整个数组会被复制一份。

package main
import "fmt"
func modifyArray(arr [3]int) {arr[0] = 100fmt.Println("Inside function:", arr) // [100 2 3]
}
func main() {arr := [3]int{1, 2, 3}modifyArray(arr)fmt.Println("Outside function:", arr) // [1 2 3]
}

2. 特点

  • 函数内对数组的修改不会影响原数组。
  • 如果数组很大,复制整个数组会影响性能。

二、传指针方式(避免复制)

1. 基本语法

为了避免复制整个数组,可以传递数组的指针:

package main
import "fmt"
func modifyArrayByPointer(arr *[3]int) {(*arr)[0] = 100fmt.Println("Inside function:", *arr) // [100 2 3]
}
func main() {arr := [3]int{1, 2, 3}modifyArrayByPointer(&arr)fmt.Println("Outside function:", arr) // [100 2 3]
}

2. 特点

  • 传递的是数组的指针,不会复制整个数组。
  • 函数内对数组的修改会影响原数组。
  • 适用于大数组,提升性能。

三、使用切片代替数组(推荐)

在 Go 中,更常见的做法是使用**切片(slice)**作为函数参数,因为切片是引用类型,传递的是底层数组的指针,不会复制整个数组。

1. 基本语法

package main
import "fmt"
func modifySlice(s []int) {s[0] = 100fmt.Println("Inside function:", s) // [100 2 3]
}
func main() {arr := [3]int{1, 2, 3}slice := arr[:] // 将数组转换为切片modifySlice(slice)fmt.Println("Outside function:", arr) // [100 2 3]
}

2. 特点

  • 切片是引用类型,传递的是底层数组的指针。
  • 函数内对切片的修改会影响原数组。
  • 适用于动态长度的数据,更灵活。

四、多维数组作为参数

多维数组也可以作为函数参数,但需要明确指定每一维的长度(除了第一维)。

1. 基本语法

package main
import "fmt"
func printMatrix(matrix [3][2]int) {for i := 0; i < 3; i++ {for j := 0; j < 2; j++ {fmt.Printf("%d ", matrix[i][j])}fmt.Println()}
}
func main() {matrix := [3][2]int{{1, 2},{3, 4},{5, 6},}printMatrix(matrix)
}

2. 特点

  • 多维数组的长度必须严格匹配函数参数的声明。
  • 如果长度不固定,建议使用切片的切片([][]int)。

五、总结

方式特点适用场景
传值复制整个数组,函数内修改不影响原数组小数组,不希望原数组被修改
传指针传递数组指针,函数内修改影响原数组大数组,避免复制
传切片引用传递,函数内修改影响原数组动态长度数据,推荐使用
多维数组需明确指定长度,灵活性较低固定维度的矩阵数据

六、推荐做法

  1. 优先使用切片:除非明确需要固定长度的数组,否则推荐使用切片。
  2. 大数组传指针:如果必须使用数组且数组较大,建议传递指针。
  3. 避免多维数组:如果维度不固定,建议使用切片的切片([][]int)。

数组进行排序

在 Go 语言中,可以使用标准库中的 sort 包对数组进行排序。不过需要注意的是,Go 的 sort 包主要针对的是切片(slice),而不是数组(array)。因此,通常我们会先将数组转换为切片,再进行排序操作。
下面我们详细讲解如何对数组进行排序,包括升序、降序、自定义排序等场景。

一、基本排序(升序)

1. 将数组转为切片并排序

Go 的 sort.Intssort.Float64ssort.Strings 等函数只能对切片操作,因此我们需要先将数组转为切片。

package main
import ("fmt""sort"
)
func main() {arr := [5]int{5, 2, 6, 3, 1}slice := arr[:] // 转为切片sort.Ints(slice) // 升序排序fmt.Println("Sorted slice:", slice) // [1 2 3 5 6]fmt.Println("Original array:", arr) // [1 2 3 5 6]
}

注意:由于切片是对底层数组的引用,排序后原数组也会被修改。


二、降序排序

Go 的 sort 包没有直接提供降序排序的函数,但可以使用 sort.Reverse 实现降序排序。

package main
import ("fmt""sort"
)
func main() {arr := [5]int{5, 2, 6, 3, 1}slice := arr[:]sort.Sort(sort.Reverse(sort.IntSlice(slice))) // 降序排序fmt.Println("Sorted slice (desc):", slice) // [6 5 3 2 1]
}

三、自定义排序

如果数组元素是结构体,或者需要按照自定义规则排序,可以实现 sort.Interface 接口。

1. 示例:按结构体字段排序

package main
import ("fmt""sort"
)
type Person struct {Name stringAge  int
}
type ByAge []Person
func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func main() {people := []Person{{"Alice", 30},{"Bob", 25},{"Charlie", 35},}sort.Sort(ByAge(people)) // 按 Age 升序排序fmt.Println("Sorted by age:", people)// Output: [{Bob 25} {Alice 30} {Charlie 35}]
}

四、稳定性排序

Go 的 sort 包提供了稳定排序 sort.Stable(),保证相等元素的相对顺序不变。

package main
import ("fmt""sort"
)
func main() {arr := [5]int{5, 2, 6, 2, 1}slice := arr[:]sort.Stable(sort.IntSlice(slice)) // 稳定排序fmt.Println("Stable sorted slice:", slice) // [1 2 2 5 6]
}

五、总结

排序方式方法适用场景
升序排序sort.Ints() / sort.Float64s() / sort.Strings()基本类型排序
降序排序sort.Reverse(sort.IntSlice())需要降序时
自定义排序实现 sort.Interface结构体或复杂规则排序
稳定排序sort.Stable()需要保持相等元素顺序

六、注意事项

  1. 数组 vs 切片:Go 的 sort 包主要针对切片,数组需要先转为切片。
  2. 引用影响:切片排序会影响原数组,因为切片是对数组的引用。
  3. 性能考虑:对于大型数组,排序是 O(n log n) 的时间复杂度,合理使用。

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

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

相关文章

基于Java+MySQL 实现(Web)网上商城

悦桔拉拉商城1. 课设目的可以巩固自己之前所学的知识&#xff0c;以及学习更多的新知识。可以掌握业务流程&#xff0c;学习工作的流程。2. 开发环境硬件环境&#xff1a;Window11 电脑、Centos7.6 服务器软件环境&#xff1a;IntelliJ IDEA 2021.1.3 开发工具JDK 16 运行环境M…

高并发抢单系统核心实现详解:Redisson分布式锁实战

一、方法整体流程解析 #mermaid-svg-MROZ2xF7WaNPaztA {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-MROZ2xF7WaNPaztA .error-icon{fill:#552222;}#mermaid-svg-MROZ2xF7WaNPaztA .error-text{fill:#552222;strok…

Android12 User版本开启adb root, adb remount, su, 关闭selinux

开启adb root 直接看adb源码&#xff1a; __android_log_is_debuggable就是判断ro.debuggable属性值&#xff0c;感兴趣可以在 源码下grep下实现看看。auth_required :在adb源码下定义的全局变量&#xff0c;默认等于true,。看名字就是是否需要用户授权的flag, 这里不再继续跟…

金融专业高分简历撰写指南

一、金融求职简历原则&#xff1a;深度与亮点并存在金融行业求职时&#xff0c;一份出色的简历需突出经历深度与亮点。01 教育背景需如实填写毕业院校、专业、GPA及所学课程。金融行业不少公司对求职者学校和学历有严格标准&#xff0c;如“985”“211”院校或硕士以上学历等。…

专题:2025生命科学与生物制药全景报告:产业图谱、投资方向及策略洞察|附130+份报告PDF、原数据表汇总下载

原文链接&#xff1a;https://tecdat.cn/?p43526 过去一年&#xff0c;全球生命科学VC融资回暖至1021.5亿美元&#xff0c;并购交易虽下滑23%却聚焦关键赛道&#xff0c;创新药管线中GLP-1受体激动剂以170亿美元市场规模领跑&#xff0c;AI技术将研发周期缩短60%……这些数据背…

Compose笔记(四十)--ClickableText

这一节主要了解一下Compose中的ClickableText&#xff0c;在Jetpack Compose中&#xff0c;ClickableText是用于创建可点击文本的组件&#xff0c;其核心功能是通过声明式语法将文本设置为交互式元素&#xff0c;用户点击时可触发特定操作。简单总结如下:API含义 text&#xff…

面试必刷的数组三连:原地删除与合并

坚持用 清晰易懂的图解 多语言代码&#xff0c;让每道题变得简单&#xff01; 呆头个人主页详情 呆头个人Gitee代码仓库 呆头详细专栏系列 座右铭&#xff1a; “不患无位&#xff0c;患所以立。” 面试必刷的数组三连&#xff1a;原地删除与合并前言目录1.移除元素2.删除有序…

力扣经典算法篇-41-旋转图像(辅助数组法,原地旋转法)

1、题干 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a;输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]]…

译|用户增长策略如何使用因果机器学习的案例

来自上传文件中的文章《[Causal Machine Learning for Growth: Loyalty Programs, LTV, and What to Do When You Can’t Experiment | by Torty Sivill | Towards AI]》 本文探讨了当 A/B 测试不可行时&#xff0c;如何利用因果推断从历史数据中获取洞察。技术亮点在于通过构建…

java~final关键字

final关键字final基本介绍final的使用细节final基本介绍 final是最终的意思&#xff0c;可以修饰类&#xff0c;属性&#xff0c;方法&#xff0c;局部变量什么时候会要使用到final呢&#xff1f; 1.想要类不被继承时 2.不希望类的某个属性的值被改变时 3.不想父类的某个方法被…

Node.js(四)之数据库与身份认证

数据库与身份认证 目录 数据库与身份认证 十三、数据库的基本概念 13.1 什么是数据库 13.2 常见的数据库及分类 13.3 传统型数据库的数据组织结构 1. Excel 的数据组织结构 2. 传统型数据库的数据组织结构 3. 实际开发中库、表、行、字段的关系 十四、安装并配置MySQ…

SpringBoot+SpringMVC常用注解

文章目录发展历程项目创建项目结构入门案例配置文件的两种方式&#xff1a;只能使用一种创建项目二入门案例常用知识及注解Controller:类上面加&#xff0c;SpringMVC的注解GetMapping:方法上面加Spring框架的两项核心功能Component:组件。控制反转&#xff0c;加在业务类上面&…

标准GS相位恢复算法

标准GS相位恢复算法详解与MATLAB实现 Gerchberg-Saxton (GS) 算法是一种经典的相位恢复方法&#xff0c;广泛应用于光学成像、衍射成像和全息技术等领域。该算法通过迭代过程从未知相位的强度测量中恢复相位信息。 算法原理 GS算法的核心思想是利用傅里叶变换关系在空间域和频率…

【Linux网络编程基础--socket地址API】

一、主机字节序和网络字节序主机字节序&#xff08;Host Byte Order&#xff09;&#xff1a;你当前电脑的内存字节顺序&#xff08;比如 x86 是小端&#xff09;网络字节序&#xff08;Network Byte Order&#xff09;&#xff1a;统一规定为大端序&#xff08;高位字节在高位…

Linux路径MTU发现(Path MTU Discovery, PMTU)

Linux路径MTU发现&#xff08;Path MTU Discovery, PMTU&#xff09;机制是TCP/IP协议栈中确保数据包高效传输的核心技术。其核心目标是动态探测源主机到目的主机路径上的最小MTU&#xff08;Maximum Transmission Unit&#xff09;&#xff0c;从而避免IP分片&#xff0c;提升…

【MySQL进阶】------MySQL程序

MySQL程序简介 MySQL安装完成通常会包含如下程序&#xff1a; Linux系统程序⼀般在 /usr/bin⽬录下&#xff0c;可以通过命令查看&#xff1a; windows系统⽬录&#xff1a;你的安装路径\MySQL Server 8.0\bin&#xff0c;可以通过命令查看&#xff1a; 每个 MySQL 程序都有许…

Linux大页内存导致服务内存不足

Linux大页内存导致服务内存不足的解决方法 大页内存&#xff08;Huge Pages&#xff09;是Linux内核提供的一种机制&#xff0c;用于减少TLB&#xff08;转换后备缓冲区&#xff09;的压力&#xff0c;提高内存访问性能。然而&#xff0c;如果配置不当&#xff0c;大页内存可能…

超宽带测距+测角+无线通信一体化模组:智能门锁、智能遥控器、AR头戴、智能穿戴

超宽带测距测角无线通信一体化模组&#xff1a;智能门锁、智能遥控器、AR头戴、智能穿戴UWB测距测角技术&#xff0c;因其高精度、低延迟、抗干扰能力&#xff0c;正广泛应用于“人-物-设备”的空间感知场景&#xff0c;成为构建智能空间和精准互动的重要底层技术。代表厂商与产…

基于单片机空气质量检测/气体检测系统

传送门 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目速选一览表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目功能速览 概述 随着环境污染问题日益严重&#xff0c;空气质量监测成为社会关注的焦点。基于单片机的空气质量检…

网络安全 | 从 0 到 1 了解 WAF:Web 应用防火墙到底是什么?

&#x1f914; 写在前面 2020年 我参加公司的安全技能大赛&#xff0c;队友在实操环节启用了 WAF 防火墙&#xff0c;这是我第一次接触到 Web 应用防火墙。作为一个 Web 开发老鸟&#xff0c;真是羞愧呀&#x1f602;。 &#x1f510; Web应用防火墙 WAF 全称是 Web Applica…