当前位置: 首页 > news >正文

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 的扩容机制

  1. 判断新申请的容量是否大于旧容量的两倍。如果是,则最终容量就是新申请的容量
  2. 如果新申请的容量不满足上一步的条件,判断旧切片长度是否小于 1024。如果是,则最终容量就是旧容量的两倍
  3. 如果旧切片长度大于等于 1024,则进入循环计算最终容量。从旧容量开始,每次增加原来容量的 1/4,直到最终容量大于等于新申请的容量
  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 会发生什么&#xff1f; 允许对值为 nil 的 slice 添加元素&#xff0c;但是对值为 nil 的 map 添加元素时会造成运行时 panic。 // map错误示例 func main() {var m map[string]intm["one"] 1 // error: panic: assignment to entry …...

冠达管理:哪里查中报预增?

中报季行将到来&#xff0c;投资者开端重视公司的成绩体现。中报预增是投资者最关心的论题之一&#xff0c;因为这意味着公司未来成绩的增加潜力。但是&#xff0c;怎么查找中报预增的信息呢&#xff1f;本文将从多个视点分析这个问题。 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 当涉及到处理鼠标输入的时候&#xff0c;Input.GetMouseButtonDown 是一个常用的函数。它可以用来检测鼠标按键是否在特定帧被按下。下面我会详细介绍这个函数&#xff0c;并举两个例子说明如何使用它。 函数签名…...

链游再进化 Web3版CSGO来袭

过去几年&#xff0c;游戏开发者们一直希望借Web3这个价值流通网络&#xff0c;改造传统游戏的经济系统&#xff0c;将虚拟资产的掌管权交给用户&#xff0c;让资产自由地在市场流通。 Web3游戏发展史上&#xff0c;涌现过CryptoKitties、Axie Infinity两大爆款&#xff0c;但…...

WordPress用于您的企业网站的优点和缺点

如今&#xff0c;WordPress 被广泛认为是一个可靠、可扩展且安全的平台&#xff0c;能够为商业网站提供支持。然而&#xff0c;许多人质疑 WordPress 是否是适合企业的平台。 这就是我们创建本指南的原因。通过探索 WordPress 的优点和缺点&#xff0c;您可以确定世界上最受欢…...

~600行ANSI C代码实现RISC-V CPU核

今天在GitHub上看到一个C语言项目&#xff0c;用大约600行代码实现了一个RISC-V CPU核&#xff0c;甚为感叹&#xff0c;分享一下。不管是学习C&#xff0c;还是学习RISC-V&#xff0c;这个项目都有非常高的学习价值&#xff0c;开源万岁&#xff01; rv 用 ANSI C 编写的RISC…...

【从零学习python 】55.Python中的序列化和反序列化,JSON与pickle模块的应用

文章目录 序列化和反序列化JSON模块pickle模块进阶案例 序列化和反序列化 通过文件操作&#xff0c;我们可以将字符串写入到一个本地文件。但是&#xff0c;如果是一个对象(例如列表、字典、元组等)&#xff0c;就无法直接写入到一个文件里&#xff0c;需要对这个对象进行序列…...

【C++】详解内存中的堆和栈

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

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管脚输出时钟配置

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

“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI 指数的生态质量评价

近年来&#xff0c;国内外学者在生态系统的敏感性、适应能力和潜在影响等方面开展了大量的生态脆弱性研究&#xff0c;他们普遍将生态脆弱性概念与农牧交错带、喀斯特地区、黄土高原区、流域、城市等相结合&#xff0c;评价不同类型研究区的生态脆弱特征&#xff0c;其研究内容…...

【大虾送书第六期】搞懂大模型的智能基因,RLHF系统设计关键问答

目录 ✨1、RLHF是什么&#xff1f; ✨2、RLHF适用于哪些任务&#xff1f; ✨3、RLHF和其他构建奖励模型的方法相比有何优劣&#xff1f; ✨4、什么样的人类反馈才是好的反馈 ✨5、RLHF算法有哪些类别&#xff0c;各有什么优缺点&#xff1f; ✨6、RLHF采用人类反馈会带来哪些局…...

超越函数界限:探索JavaScript函数的无限可能

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 &#x1f4da; 前言 &#x1f4d8; 1. 函数的基本概念 &#x1f4df; 1.1 函数的定义和调用 &#x1f4df; 1.2 …...

PHP实现轻量级WEB服务器接收HTTP提交的RFID刷卡信息并回应驱动读卡器显示播报语音

本示例使用的读卡器&#xff1a;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 查询中用于将之前的查询结果传递给后续的查询操作。它可以用来控制查询的流程&#xff0c;并且常常与其他语句如 MATCH、RETURN、CREATE、DELETE 等一起使用。以下是一些常用的示例和解释&#xff1a; 基本用法&#xff1a; MATCH (p:Person) WITH p RETU…...

60页数字政府智慧政务大数据资源平台项目可研方案PPT

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

循环神经网络RNN完全解析:从基础理论到PyTorch实战

目录 一、循环神经网络全解1.1 什么是循环神经网络网络结构工作原理数学模型RNN的优缺点总结 1.2 循环神经网络的工作原理RNN的时间展开数学表述信息流动实现示例梯度问题&#xff1a;梯度消失和爆炸总结 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 - 系列文章链接汇总》…...

网络安全法律

立法的必要性&#xff1a;网络渗透&#xff0c;网络入侵&#xff0c;网络诈骗&#xff0c;网上钓鱼侵犯知识产权&#xff0c;宣传恐怖主义&#xff0c;极端主义等伤害共鸣利益的行为越发猖狂 信息系统运维安全管理规定&#xff08;范文&#xff09;| 资料 过程: 14-16 草案初…...

Redis缓存问题(穿透, 击穿, 雪崩, 污染, 一致性)

目录 1.什么是Redis缓存问题&#xff1f; 2.缓存穿透 3.缓存击穿 4.缓存雪崩 5.缓存污染&#xff08;或满了&#xff09; 5.1 最大缓存设置多大 5.2 缓存淘汰策略 6.数据库和缓存一致性 6.1 4种相关模式 6.2 方案&#xff1a;队列重试机制 6.3 方案&#xff1a;异步更新缓…...

网络时代拟态环境的复杂化

信息在网络上的制作、编码、传播机制和传统媒介有本质的区别&#xff0c;即传播者和 受传者的角色交叉&#xff0c;而且互联网本身可看作另一个有别于现实环境的虚拟世界&#xff0c;因 此网络媒介所营造出的拟态环境在一定程度上独立于传统大众传播的拟态环境。 一个是传统…...

湘潭大学 湘大 XTU OJ 1055 整数分类 题解(非常详细)

链接 整数分类 题目 Description 按照下面方法对整数x进行分类&#xff1a;如果x是一个个位数&#xff0c;则x属于x类&#xff1b;否则将x的各位上的数码累加&#xff0c;得到一个新的x&#xff0c;依次迭代&#xff0c;可以得到x的所属类。比如说24&#xff0c;246&#…...

什么是视频的编码和解码

这段描述中&#xff0c;视频解码能力和视频编码能力指的是不同的处理过程。视频解码是将压缩过的视频数据解开并还原为可播放的视频流&#xff0c;而视频编码是将原始视频数据压缩成更小的尺寸&#xff0c;以减少存储空间和传输带宽。在这个上下文中&#xff0c;解码能力和编码…...

LeetCode 2681. Power of Heroes【排序,数学,贡献法】2060

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

AVL树的讲解

算法拾遗三十八AVL树 AVL树AVL树平衡性AVL树加入节点AVL删除节点AVL树代码 AVL树 AVL树具有最严苛的平衡性&#xff0c;&#xff08;增、删、改、查&#xff09;时间复杂度为O&#xff08;logN&#xff09;&#xff0c;AVL树任何一个节点&#xff0c;左树的高度和右树的高度差…...

Unity 之 Input类

文章目录 总述具体介绍 总述 Input 类是 Unity 中用于处理用户输入的重要工具&#xff0c;它允许您获取来自键盘、鼠标、触摸屏和控制器等设备的输入数据。通过 Input 类&#xff0c;您可以轻松地检测按键、鼠标点击、鼠标移动、触摸、控制器按钮等用户输入事件。以下是关于 I…...

亚信科技AntDB数据库连年入选《中国DBMS市场指南》代表厂商

近日&#xff0c;全球权威ICT研究与顾问咨询公司Gartner发布了2023年《Market Guide for DBMS, China》&#xff08;即“中国DBMS市场指南”&#xff09;&#xff0c;该指南从市场份额、技术创新、研发投入等维度对DBMS供应商进行了调研。亚信科技是领先的数智化全栈能力提供商…...

AMBA总线协议(3)——AHB(一)

目录 一、前言 二、什么是AHB总线 1、概述 2、一个典型的基于AHB总线的微处理器架构 3、基本的 AHB 传送特性 三、AMBA AHB总线互联 四、小结 一、前言 在之前的文章中我们初步的了解了一下AMBA总线中AHB,APB,AXI的信号线及其功能&#xff0c;从本文开始我们…...

Git commit与pull的先后顺序

Git commit与pull的先后顺序_git先pull再commit_Mordor Java Girl的博客-CSDN博客 ​ 编辑yucoang2020.04.21 回复 28 先pull再commit的话, 你的commit也就不再纯粹了. 这一个commit不再是"你所编辑的xxx功能, 而是"别人所编辑的你所编辑的xxx". 我认为提交历…...