Golang 基础语法问答
使用值为 nil 的 slice、map 会发生什么?
允许对值为 nil 的 slice 添加元素,但是对值为 nil 的 map 添加元素时会造成运行时 panic。
// map错误示例
func main() {var m map[string]intm["one"] = 1 // error: panic: assignment to entry in nil map// m := make(map[string]int) // map的正确声明, 分配了实际的内存
} // slice正确示例
func main() {var s []ints = append(s, 1)
}
访问 map 中的 key,需要注意什么?
当访问 map 中不存在的 key 时,Go 会返回元素对应数据类型的零值,比如 nil、“” 、false 和 0,即取值操作总是有值返回的,故不能通过取出来的值来判断 key 是否存在。
检查 key 是否存在可以用 map 直接访问,检查返回的第二个参数即可。
// 错误的key检测方式
func main() {x := map[string]string{"one": "2", "two": "", "three": "3"}if v := x["two"]; v == "" {fmt.Println("key two is no entry") // 不管键two存不存在都会返回的空字符串}
}// 正确示例
func main() {x := map[string]string{"one": "2", "two": "", "three": "3"}if _, ok := x["two"]; !ok {fmt.Println("key two is no entry")}
}
string 类型的值可以修改吗?
不能,尝试使用索引遍历字符串,来更新字符串中的个别字符时,是不允许的。
string 类型的值是只读的二进制字节切片,如果真要修改字符串中的字符,先将 string 转为 []byte 修改后,再转为 string 即可。
// 修改字符串的错误示例
func main() {x := "text"x[0] = "T" // error: cannot assign to x[0]fmt.Println(x)
}// 修改示例
func main() {x := "text"xBytes := []byte(x)xBytes[0] = 'T' // 注意此时的T是rune类型x = string(xBytes)fmt.Println(x) // Text
}
switch 中如何强制执行下一个 case 代码块?
switch 语句中的 case 代码块会默认带上 break,但可以使用 fallthrough 来强制执行下一个 case 代码块。
func main() {isSpace := func(char byte) bool {switch char {case ' ': // 空格符会直接break, 返回 false// fallthrough // 返回truecase '\t':return true}return false}fmt.Println(isSpace('\t')) // truefmt.Println(isSpace(' ')) // false
}
切片和数组的区别?
- 数组是具有固定长度,且拥有零个或者多个,相同数据类型元素的序列
- 数组的长度是数组类型的一部分,所以 [3]int 和 [4]int 是两种不同的数组类型
- 数组需要指定大小,不指定也会根据初始化的自动推算出大小,在初始化后长度是固定的,无法修改其长度
- 数组是值传递,数组是内置类型,是一组同类型数据的集合,它是值类型,通过从 0 开始的下标索引访问元素值
var array [10]int
var array =[5]int{1,2,3,4,5}
- 切片表示一个拥有相同类型元素的可变长度的序列
- 切片是一种轻量级的数据结构,它有三个属性:指针、长度和容量
- 切片不需要指定大小
- 切片是地址传递
- 切片可以通过数组来初始化,也可以通过内置函数 make() 来初始化 ,初始化时 len=cap,在追加元素时如果容量 cap 不足,将按 len 的 2 倍扩容
var slice []type = make([]type, len)
new 和 make 的区别?
- new 的作用是初始化一个指向类型的指针(*T)
- new 函数是内建函数,函数定义:func new(Type) *Type
- 使用 new 函数来分配空间
- 传递给 new 函数的是一个类型,不是一个值,返回值是指向这个新分配的零值的指针
- make 的作用是为 slice、map 或 chan 初始化,并返回引用 (T)
- make 函数是内建函数,函数定义:func make(Type, size IntegerType) Type,第一个参数是一个类型,第二个参数是长度,返回值是一个类型
- make(T, args) 函数的目的与 new(T) 不同,它仅仅用于创建 Slice、Map 和 Channel,并且返回类型是 T(不是 *T)的一个初始化的(不是零值)的实例
go 语言中的 for 循环
for 循环支持 continue 和 break 来控制循环,但是它提供了一个更高级的 break,可以选择中断哪一个循环。for 循环不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的方式来初始化多个变量。
outerloop:
for i := 0; i < 3; i++ {for j := 0; j < 3; j++ {if j == 2 {break outerloop}fmt.Println(i, j)}
}
// 在上述示例中, 我们使用了break outerloop来指定要中断的是外层循环。当内部循环中的j的值等于2时, 执行 break outerloop, 这样整个循环就会被完全中断, 不再继续执行。for i, j := 0, 0; i < 3; i, j = i+1, j+1 {fmt.Println(i, j)
}
// 在这个示例中, 我们使用了平行赋值的方式来初始化i和j两个变量。每次循环迭代, i和j分别会自增1, 并通过平行赋值将新的值重新关联给它们。
go 语言中的引用类型包含哪些?
数组切片(slice)、字典(map)、通道(channel)、接口(interface)。
go 语言的 main 函数
- main 函数不能带参数
- main 函数不能定义返回值
- main 函数所在的包必须为 main 包
- main 函数中可以使用 flag 包来获取和解析命令行参数
go 语言中的静态类型声明
在 Go 语言中,静态类型声明是指在声明变量、函数或方法时显式指定其类型。静态类型声明是 Go 语言的一个重要特性,它使得变量在编译阶段就能够被确定其类型,并且在编译过程中进行静态类型检查。
静态类型声明的语法格式通常是在变量名或函数名后面加上类型标识符,用于明确指定变量的类型。
var count int // 声明一个名为count的整数类型变量
var message string // 声明一个名为message的字符串类型变量
func add(a int, b int) int { // 声明一个名为add的函数, 接收两个整数类型参数, 返回一个整数类型结果return a + b
}
在上述示例中,使用了 int 和 string 来显式声明变量 count 和 message 的类型,以及函数 add 的参数类型和返回值类型。
静态类型声明的优势在于可以提供强类型检查。编译器可以在编译阶段对类型信息进行检查,包括类型的兼容性、正确的方法调用等,从而减少在运行时出现类型错误的可能性。这有助于提高代码的可靠性和安全性。
此外,静态类型声明还使代码更易于理解和维护。通过明确指定变量的类型,可以对变量的用途有更好的描述,减少了对类型的猜测和理解上的困惑。
总而言之,Go 语言中的静态类型声明是一种为变量、函数和方法显式指定类型的机制,它提供了静态类型检查和更好的代码可读性、可维护性。
Slice 的底层实现
切片是基于数组实现的,它的底层是数组,它自己本身非常小,可以理解为是对底层数组的抽象。因为基于数组实现,所以它的底层的内存是连续分配的,效率非常高,还可以通过索引获得数据,可以迭代以及垃圾回收优化。
切片本身并不是动态数组或者数组指针。它内部实现的数据结构通过指针引用底层数组,设定相关属性,将数据读写操作限定在指定的区域内。切片本身是一个只读对象,其工作机制类似于数组指针的一种封装。
切片对象非常小,是因为它是只有 3 个字段的数据结构,这 3 个字段就是 Go 语言操作底层数组的元数据。
- 指向底层数组的指针
- 切片的长度
- 切片的容量
Slice 的扩容机制
- 判断新申请的容量是否大于旧容量的两倍。如果是,则最终容量就是新申请的容量
- 如果新申请的容量不满足上一步的条件,判断旧切片长度是否小于 1024。如果是,则最终容量就是旧容量的两倍
- 如果旧切片长度大于等于 1024,则进入循环计算最终容量。从旧容量开始,每次增加原来容量的 1/4,直到最终容量大于等于新申请的容量
- 如果计算出的最终容量超出了限制(即溢出),则最终容量就是新申请的容量
- 情况一:当原数组还有容量可以扩容时,扩容后的数组仍然指向原来的数组。这就意味着对一个切片的操作可能会影响到多个指针,因为它们指向的是同一个地址的切片
- 情况二:如果原来数组的容量已经达到最大值,再次扩容会导致 Go 语言默认先开辟一片新的内存区域,并将原来的值复制过去,然后执行 append() 操作。这种情况不会对原数组造成任何影响
要复制一个 Slice,最好使用 Copy 函数。
Map底层实现
Go 中 map 的底层实现是一个散列表,因此实现 map 的过程实际上就是实现散列表的过程。
在这个散列表中,主要出现的结构体有两个,一个叫 hmap(a header for a go map),一个叫 bmap(a bucket for a Go map,通常称为 bucket)。
我们只需关注标红的字段:buckets 数组。Go 的 map 中用于存储的结构是 bucket 数组(即 bmap)。
相比于 hmap,bucket 的结构显得简单一些,标橙的字段依然是核心,我们使用的 map 中的 key 和 value 就存储在这里。
“高位哈希值”数组记录的是当前 bucket 中 key 相关的“索引”,还有一个字段是一个指向扩容后的 bucket 的指针,使得 bucket 会形成一个链表结构。
Go 把求得的哈希值按照用途一分为二:高位和低位。低位用于寻找当前 key 属于 hmap 中的哪个 bucket,而高位用于寻找 bucket 中的哪个 key。
注意:map 中的 key/value 值都是存到同一个数组中的。这样做的好处是,在 key 和 value 的长度不同时,可以消除 padding 带来的空间浪费。
map 的扩容:当 Go 的 map 长度增长到大于加载因子所需的 map 长度时,Go 语言就会产生一个新的 bucket 数组,然后把旧的 bucket 数组移到一个属性字段 oldbucket 中。
注意:并不是立刻把旧的数组中的元素转移到新的 bucket 中,而是只有当访问到具体的某个 bucket 的时候,才会把 bucket 中的数据转移到新的 bucket 中。
在 range 迭代 slice 时,如何修改值?
在 range 迭代中,得到的值其实是元素的一份值拷贝,更新拷贝并不会更改原来的元素,即拷贝的地址并不是原有元素的地址。
func main() {data := []int{1, 2, 3}for _, v := range data {v *= 10 // data中原有元素是不会被修改的}fmt.Println("data: ", data) // data: [1 2 3]
}
如果要修改原有元素的值,应该使用索引直接访问。
func main() {data := []int{1, 2, 3}for i, v := range data {data[i] = v * 10 }fmt.Println("data: ", data) // data: [10 20 30]
}
如果你的集合保存的是指向值的指针,需稍作修改。依旧需要使用索引访问元素,不过可以使用 range 出来的元素直接更新原有值。
func main() {data := []*struct{ num int }{{1}, {2}, {3}}for _, v := range data {v.num *= 10 // 直接使用指针更新}fmt.Println(data[0], data[1], data[2]) // &{10} &{20} &{30}
}
相关文章:

Golang 基础语法问答
使用值为 nil 的 slice、map 会发生什么? 允许对值为 nil 的 slice 添加元素,但是对值为 nil 的 map 添加元素时会造成运行时 panic。 // map错误示例 func main() {var m map[string]intm["one"] 1 // error: panic: assignment to entry …...

冠达管理:哪里查中报预增?
中报季行将到来,投资者开端重视公司的成绩体现。中报预增是投资者最关心的论题之一,因为这意味着公司未来成绩的增加潜力。但是,怎么查找中报预增的信息呢?本文将从多个视点分析这个问题。 1.证券交易所网站 证券交易所网站是投资…...

docker安装Oracle11gR2
文章目录 目录 文章目录 前言 一、前期准备 二、具体配置 2.1 配置oracle容器 2.2 配置navicat连接 总结 前言 使用docker模拟oracle环境 一、前期准备 安装好docker #拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g #启动 docker run -…...

unity 之 Input.GetMouseButtonDown 的使用
文章目录 Input.GetMouseButtonDown Input.GetMouseButtonDown 当涉及到处理鼠标输入的时候,Input.GetMouseButtonDown 是一个常用的函数。它可以用来检测鼠标按键是否在特定帧被按下。下面我会详细介绍这个函数,并举两个例子说明如何使用它。 函数签名…...
链游再进化 Web3版CSGO来袭
过去几年,游戏开发者们一直希望借Web3这个价值流通网络,改造传统游戏的经济系统,将虚拟资产的掌管权交给用户,让资产自由地在市场流通。 Web3游戏发展史上,涌现过CryptoKitties、Axie Infinity两大爆款,但…...

WordPress用于您的企业网站的优点和缺点
如今,WordPress 被广泛认为是一个可靠、可扩展且安全的平台,能够为商业网站提供支持。然而,许多人质疑 WordPress 是否是适合企业的平台。 这就是我们创建本指南的原因。通过探索 WordPress 的优点和缺点,您可以确定世界上最受欢…...
~600行ANSI C代码实现RISC-V CPU核
今天在GitHub上看到一个C语言项目,用大约600行代码实现了一个RISC-V CPU核,甚为感叹,分享一下。不管是学习C,还是学习RISC-V,这个项目都有非常高的学习价值,开源万岁! rv 用 ANSI C 编写的RISC…...
【从零学习python 】55.Python中的序列化和反序列化,JSON与pickle模块的应用
文章目录 序列化和反序列化JSON模块pickle模块进阶案例 序列化和反序列化 通过文件操作,我们可以将字符串写入到一个本地文件。但是,如果是一个对象(例如列表、字典、元组等),就无法直接写入到一个文件里,需要对这个对象进行序列…...

【C++】详解内存中的堆和栈
2023年8月20日,周日早上 感觉很多东西还没吃透,很多疑问还没解决。 这篇文章可能会不定期更新。 还没解释为什么栈的空间有限,而堆的空间很大 还没解释栈和堆在内存中的位置 ...... 目录 怎么申请栈空间语法举例说明 怎么申请堆空间语法…...

QCustomPlot横坐标为毫秒级的时间轴数据展示的实时刷新数据功能
头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimer>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();int realtime…...

STM32/AT32 MCO管脚输出时钟配置
前言:最近在学以太网通讯,发现RMII接口配置的时钟管脚有MCU自己输出,想要看看是怎么输出的,对此进行记录 1、交接项目项目上使用的是PA8管脚来输出时钟50MHZ,提供给上面refclk。 先看手册 PA8的复用功能具备将MCU时钟…...

“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI 指数的生态质量评价
近年来,国内外学者在生态系统的敏感性、适应能力和潜在影响等方面开展了大量的生态脆弱性研究,他们普遍将生态脆弱性概念与农牧交错带、喀斯特地区、黄土高原区、流域、城市等相结合,评价不同类型研究区的生态脆弱特征,其研究内容…...

【大虾送书第六期】搞懂大模型的智能基因,RLHF系统设计关键问答
目录 ✨1、RLHF是什么? ✨2、RLHF适用于哪些任务? ✨3、RLHF和其他构建奖励模型的方法相比有何优劣? ✨4、什么样的人类反馈才是好的反馈 ✨5、RLHF算法有哪些类别,各有什么优缺点? ✨6、RLHF采用人类反馈会带来哪些局…...

超越函数界限:探索JavaScript函数的无限可能
🎬 岸边的风:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 📚 前言 📘 1. 函数的基本概念 📟 1.1 函数的定义和调用 📟 1.2 …...

PHP实现轻量级WEB服务器接收HTTP提交的RFID刷卡信息并回应驱动读卡器显示播报语音
本示例使用的读卡器:RFID网络WIFI无线TCP/UDP/HTTP可编程二次开发读卡器POE供电语音-淘宝网 (taobao.com) <?php mb_http_output(utf-8); $port88; $socket socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $bool socket_bind($socket, "0.0.0.0",…...
Neo4j之with基础
WITH 语句在 Cypher 查询中用于将之前的查询结果传递给后续的查询操作。它可以用来控制查询的流程,并且常常与其他语句如 MATCH、RETURN、CREATE、DELETE 等一起使用。以下是一些常用的示例和解释: 基本用法: MATCH (p:Person) WITH p RETU…...

60页数字政府智慧政务大数据资源平台项目可研方案PPT
导读:原文《60页数字政府智慧政务大数据资源平台项目可研方案PPT》(获取来源见文尾),本文精选其中精华及架构部分,逻辑清晰、内容完整,为快速形成售前方案提供参考。 项目需求分析 项目建设原则和基本策略…...

循环神经网络RNN完全解析:从基础理论到PyTorch实战
目录 一、循环神经网络全解1.1 什么是循环神经网络网络结构工作原理数学模型RNN的优缺点总结 1.2 循环神经网络的工作原理RNN的时间展开数学表述信息流动实现示例梯度问题:梯度消失和爆炸总结 1.3 循环神经网络的应用场景文本分析与生成1.3.1 自然语言处理1.3.2 机器…...
【SA8295P 源码分析】52 - 答疑之 QNX 创建镜像、Android修改CMDLINE
【SA8295P 源码分析】52 - 答疑之 QNX 创建镜像、Android修改CMDLINE 一、QNX 侧创建 img 镜像二、QNX 侧指定只编译某一个版本三、Android定制修改selinux权限,user版本采用enforcing,userdebug版本permissive系列文章汇总见:《【SA8295P 源码分析】00 - 系列文章链接汇总》…...
网络安全法律
立法的必要性:网络渗透,网络入侵,网络诈骗,网上钓鱼侵犯知识产权,宣传恐怖主义,极端主义等伤害共鸣利益的行为越发猖狂 信息系统运维安全管理规定(范文)| 资料 过程: 14-16 草案初…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...