GO语言核心30讲 实战与应用 (第一部分)

原站地址:Go语言核心36讲_Golang_Go语言-极客时间

一、测试的基本规则和流程

1.  GO程序主要分三类测试:功能测试、性能测试,以及示例测试。

     示例测试和功能测试差不多,但它更关注程序打印出来的内容。

2. 测试文件的名称应该以被测源码文件的名称为前导,并以“_test”为后缀。

    例如,如果被测文件的名称为 demo52.go,那么测试文件的名称就是 demo52_test.go。

3. 对测试函数的名称和签名都有哪些规定? 

功能测试: 函数名称以Test为前缀,参数列表中有一个*testing.T类型的参数。

能能测试: 函数名称以Benchmark为前缀,参数列表中有一个*testing.B类型的参数。

示例测试: 函数名称以Example为前缀,对参数列表没有强制规定。

4. go test命令执行的测试流程是怎样?

(1) 检查内部命令、源码文件有效性,标记是否合法。

(2) 对每个被测代码包,依次地进行构建。

(3) 执行符合要求的测试函数。

(4) 清理临时文件,打印测试结果

5. 功能测试下,多个代码包是并发进行的。

    性能测试下,多个代码包是串行进行的。

6. 性能测试,是在所有构建步骤都做完之后,go test命令才会真正地开始进行。多个文件,多个函数,都是串行地逐个执行。目的是保证独立执行,性能测试准确。

7. 测试结果包含三部分:运行情况,测试文件路径,耗时

$ go test puzzlers/article20/q2
ok   puzzlers/article20/q2 0.008s

8. 代码没有变动情况下,go test命令 会执行把之前缓存的结果 打印出来,时间变成 "cached"。不会重复执行。

   go clean -cache 命令可以手动删除缓存数据。

  设置值gocacheverify=1 将会导致 go 命令绕过任何的缓存数据。

9. 如果测试失败了:

(1) go test命令并不会进行缓存

(2) 测试日志会被打印出来  (t.Log,t.Error)

10.  t.Fatal 和t.Fatalf ,作用是打印失败错误日志之后,立即终止测试函数并宣告测试失败

11. 解释输入性能测试命令,比如:go test -bench=. -run=^$ puzzlers/article20/q3 

      -bench:标明是执行性能测试。 -bench=.:带上 =. 表示 执行所有名称的性能测试函数

      -run:标明是执行功能测试。-run=^$:带上=^$ 表示执行所有名称为空的功能测试函数,也就是 不执行功能测试函数。  不输入这个的话,默认是会执行的,但性能测试下我们需要不执行。

12. 性能测试的结果,包含了什么数据?

$ go test -bench=. -run=^$ puzzlers/article20/q3
goos: darwin
goarch: amd64
pkg: puzzlers/article20/q3
BenchmarkGetPrimes-8      500000       2314 ns/op
PASS
ok   puzzlers/article20/q3 1.192s

    主要是在其中一句:BenchmarkGetPrimes-8      500000       2314 ns/op

    BenchmarkGetPrimes-8:执行了性能测试函数GetPrimes, 同时运行 goroutine 的逻辑 CPU 数量是 8

   500000: 函数运行时间不超过上限(默认1秒)的条件下,能执行多少次。

   2314 ns/op: 单次执行GetPrimes函数的平均耗时。

二、更多的测试手法

1. go test -cpu P : 设置测试使用多少个CPU

     P 代表着 Go 运行时系统同时运行 goroutine 的数目,也可以视为逻辑 CPU 的最大个数.

2. go test -parallel x : 设置功能测试函数的最大并发执行数。默认值是上面的P。

    这个命令只用于功能测试,对性能测试无效。

3. 性能测试中,可以通过 b.StartTimer和b.StopTimer 的联合运用,去除掉部分代码的执行时间。

    也可以用b.ResetTimer 去除在调用它之前那些代码的执行时间。

三、sync.Mutex与sync.RWMutex

1. 同步的用途: 避免多个线程同时操作一个数据块 或 一个代码块

   数据块和代码块合称 共享资源

2. 一个代码片段需要实现对共享资源的串行化访问(独占),就可以被视为一个临界区

    这样的代码片段有多个,就被称为相关临界区。

3.  Go 中,可选择的同步工具不少。其中最重要且最常用的,当属 互斥锁sync.Mutex

     互斥锁要求每当 goroutine 想进入临界区时,都需要对mutex进行锁定 mu.Lock();

     goroutine 离开临界区时,都要对mutex进行解锁 mu.Unlock()。

4. 对一个已经被锁定的互斥锁进行锁定,会立即阻塞当前的 goroutine。(互斥锁能够保护临界区的原因)

5. Go 语言系统只要发现所有的goroutine 都处于阻塞状态,就会触发 panic。

   Go 语言系统自行抛出的 panic 属于致命错误,是无法被recover函数恢复的。也就是说,一旦产生死锁,程序必然崩溃。

6. 使用互斥锁的注意事项:

(1) 不要重复锁定

(2) 不要忘记解锁,必要时使用defer语句

(3) 不要重复解锁,不要对尚未锁定的互斥锁进行解锁(会panic)

(4) 不要在多个函数之间传递互斥锁

7. 读写锁sync.RWMutex)包含了两个锁,即:读锁和写锁。

    Lock方法和Unlock方法对写锁进行锁定和解锁,

    RLock方法和RUnlock方法对读锁进行锁定和解锁。

8. 读写锁sync.RWMutex)规则:

(1) 在写锁已被锁定的情况下,再锁定写锁,会阻塞当前的 goroutine。

(2) 在写锁已被锁定的情况下,锁定读锁,也会阻塞当前的 goroutine。

(3) 在读锁已被锁定的情况下,锁定写锁,同样会阻塞当前的 goroutine。

(4) 在读锁已被锁定的情况下,试图锁定读锁,并不会阻塞当前的 goroutine。

   也就是,读锁是写锁的一部分,只要和写锁有关,就变成只有一个锁。 

9. 解锁一个写锁,会唤醒试图锁定读锁所有goroutine。

    解锁一个读锁,只会唤醒试图锁定写锁一个goroutine。唤醒哪个,取决于等待时间。

四、条件变量sync.Cond

1. 条件变量是基于互斥锁的,但并不是被用来保护临界区和共享资源。而是当共享资源的状态发生变化时,用来通知被互斥锁阻塞的线程。

2. 条件变量提供的方法有三个:等待通知(wait)、单发通知(signal)和广播通知(broadcast)

3. 条件变量怎样与互斥锁配合使用?

(1) 条件变量 配合 互斥锁 使用,需要四个组成部分,分别是:

     mailbox (int8):用于标记的变量, 用于表示 共享资源的状态是否发生了变化

     lock (sync.RWMutex): 互斥锁,用于保护共享资源与其上面mailbox的互斥锁

     sendCond(sync.Cond):发送方的条件变量,发送通知 资源状态发生变化。

     recvCond (sync.Cond):接收方的条件变量,接收通知 资源状态发生变化。

(2) sync.Cond 变量初始化的时候,需要输入 sync.Locker 指针给 sync.NewCond 函数。

     sync.Locker 是接口类型,包含 Lock()和Unlock() 两个方法。

     sync.Mutex 实现了 Lock()和Unlock(), 是 sync.Locker 的实现类型。

     所以把 sync.Mutex传入 sync.NewCond 函数,初始化 sync.Cond

(3) 发送方过程,5步:

lock.Lock()    //1. 互斥量进行锁定
for mailbox == 1 {    //2. 循环判定标记变量是否能修改
 sendCond.Wait()      //2. (我方条件变量调用Wait方法进行等待)
}
mailbox = 1            //3. 修改标记变量
lock.Unlock()          //4. 互斥量进行解锁
recvCond.Signal()      //5. 向对方条件变量调用Signal方法的发送信号

(4) 接收方过程,5步:

lock.RLock()    //1. 互斥量进行锁定
for mailbox == 0 {     //2. 循环判定标记变量,是否能修改标识
 recvCond.Wait()       //2. 调用我方条件变量的wait方法进行等待
}    
mailbox = 0            //3. 修改标记变量
lock.RUnlock()         //4. 互斥量进行解锁
sendCond.Signal()      //5. 调用对方条件变量的Signal方法发送信号。

4. sync.Cond.Wait() 方法干了些什么?

(1) 把当前goroutine加入到我方条件变量的通知队列中。

(2) 解锁互斥量 lock     (所以调用Wait()方法之前,必须先锁定互斥量lock)

(3) 把当前goroutine进入等待状态,等待唤醒,代码阻塞。

(4) goroutine被唤醒之后,锁定互斥量lock

5. 为什么要用for语句来包裹Wait方法?

    因为被唤醒不代表 标记变量 mailbox 就必然满足要求。有以下会出现仍然不满足要求的情况:

(1) 有多个 goroutine 共同在等待共享资源。

(2) 标记变量可能有多种状态。

(3) 计算机硬件问题。

6. Signal 只会唤醒一个goroutine,而Broadcast会唤醒所有的 goroutine。

7. 如果条件变量通知的时候没有 goroutine 为此等待,那么该通知就会被丢弃。

8. wait方法需要锁定互斥量,但Signal和Broadcase不需要锁定互斥量。

五、原子操作

1. 原子操作是在底层由 CPU 提供芯片级别的支持,所以绝对有效。即使在多 CPU 的系统中,仍然保证有效。

2. 原子操作sync/atomic 的速度比其他同步工具快好几个数量级。

3. 因为不能被中断,所以表示式 需要足够简单

4. sync/atomic包中提供了几种原子操作?

    加法(add)、交换(swap)、比较并交换(简称 CAS)、加载(load)、存储(store)。

    支持的数据类型有:int32、int64、uint32、uint64、uintptr、unsafe.Pointer

5. 原子操作函数需要的是 被操作值的指针,而不是这个值本身

6. 原子加法操作的函数可以做原子减法吗?

(1) 对于int32、int64来说,直接在代表差量的第二个参数力输入负值就可以。

(2) 对于uint32、uint64 来说,可以把 负值增量 赋值给一个变量,然后强转成uint32即可。

7. 比较并交换操作CAS的特点:

(1) CAS会先判断被操作变量的当前值,是否与预期的旧值相等。如果相等,就把新值赋给该变量,并返回true;否则就不赋值,直接返回false。

(2) CAS与for语句联用,可以实现简易的自旋锁。属于乐观锁,预期是共享资源状态的改变并不频繁。 而互斥量的锁属于悲观锁,预期是共享资源状态频繁改变。

8. 即使保证了写操作都是原子操作,在读操作时,也需要保证是原子操作。 避免读到没有被修改完的值。

9. 并发地读写互不相关的整数类型值,使用原子操作函数更有,因为速度比互斥锁快得多。

10. 关于sync/atomic包的类型Value:

(1) sync/atomic包的类型Value,相当于一个容器,被用来“原子地”存储和加载任意的值。只有两个指针方法:Store和Load。

(2) Value类型属于结构体类型,而结构体类型属于值类型,所以不能传入nil。

(3) 存储的第一个值,决定今后能且只能存储哪一个类型的值。

(4) 使用接口的方式无效。内部是依据被存储值的实际类型来做判断的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于EBAZ4205矿板的图像处理:12图像二值化(阈值可调)

基于EBAZ4205矿板的图像处理:12图像二值化(阈值可调) 我的项目是基于EBAZ4205矿板的阈值可调的图像阈值二值化处理,可以通过按键调整二值化的阈值,key1为阈值加1,key4为阈值减1,key2为阈值加10,key5为阈值…

【AI+音视频总结】如何在几分钟内用智能工具摘取音视频精华?揭秘下一代学习和内容创作神器!

今天无意发现一个网站,可以一步到位完成AI音视频总结。 我之前对于音视频总结的步骤还是借助 工具下载 剪映来完成的。详情可以参考之前写的一篇文章 【AI应用】模仿爆款视频二次创作短视频操作步骤 。 这里介绍的网站是 BibiGPT 。 BibiGPT AI 音视频助理 - 它是…

构建第一个ArkTS应用之@AppStorage:应用全局的UI状态存储

AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。 和AppStorage不同的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStora…

VMare Workstation安装ubuntu虚拟机异常问题处理

安装方法 ubuntu官网下载插件 异常处理 开启时报错"unable to proceed without a log file" 遇到此问题的都有一个共同点,工作目录路径上都带了数字,比如"Ubuntu 64位 01",解决方法为: 选中"Ubuntu 64位…

可视化大屏的应用:电子政务领域的巨大应用价值

可视化大屏在电子政务领域的应用价值主要体现在以下几个方面: 数据监控与分析 可视化大屏可以将政务数据以图表、地图等形式展示在大屏上,帮助政府部门实时监控和分析各项指标和数据变化。例如,可以实时显示人口统计、经济指标、环境监测等…

利用“AnaTraf“网络流量分析仪轻松诊断和优化网络

网络性能监测和诊断(NPMD)是网络管理和优化的重要环节,准确快速地定位和排除网络故障对于保障业务正常运转至关重要。作为一款专业的网络流量分析设备,AnaTraf网络流量分析仪凭借其强大的流量分析和故障诊断功能,为网络管理者提供了一个高效的网络优化解决方案。 全面掌握网络…

如何将pdf文件换成3d模型?---模大狮模型网

PDF文件是一种广泛用于文档传输和共享的格式,但在某些情况下,我们可能希望将其中的内容转换为更具交互性和视觉效果的3D模型。本文将介绍如何将PDF文件转换为3D模型,为您展示实现这一想象的步骤。 选择合适的PDF文件: 首先&#…

利用AnaTraf网络流量分析仪轻松解决网络故障问题

网络故障是每个企业都必须面对的头痛问题。如何快速定位并解决网络问题,不仅能提高员工工作效率,也能减少因网络问题而带来的经济损失。 AnaTraf网络流量分析仪就是为解决这一问题而问世的一款高性能网络诊断工具。它能够对网络流量进行全面的实时监控和分析,帮助网络管理员快…

软考中级之数据库系统工程师笔记总结(六)多媒体基础

作者:Maynor 博客之星大数据领域Top1,GitHub项目awesome-chatgpt-project作者, 大厂程序员, 全网技术矩阵粉丝7w 公众号:Maynor996📢博客主页:https://manor.blog.csdn.net 📢欢迎点赞 👍 收藏 ⭐留言 &am…

请求响应里面的日期参数

日期参数 需要在控制类使用DateTimeFormat注解 package com.ming.controller; ​ ​ import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.Rest…

1756jsp农产品销售管理系统Myeclipse开发mysql数据库C2C模式java编程计算机网页项目沙箱支付

一、源码特点 java 农产品销售管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统采用web模式,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0…

在做题中学习(53): 寻找旋转数组中的最小值

153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode) 解法:O(logn)->很可能就是二分查找 思路:再看看题目要求,可以画出旋转之后数组中元素的大小关系: 首先,数组是具有二段性的(适配二分查…

8.1 AWS创建用户池(Amazon Cognito)和用户

AWS创建用户池(Amazon Cognito)和用户 目录一、Amazon Cognito1. 创建用户池2. 添加用户 目录 一、Amazon Cognito Amazon Cognito: https://aws.amazon.com/cognito/ Amazon Cognito 是亚马逊提供的一种身份验证、授权和用户管理服务。它为开发人员提供…

韩顺平0基础学Java——第6天

p87-p109 运算符(第四章) 四种进制 二进制用0b或0B开头 十进制略 八进制用0开头 十六进制0x或0X开头,其中的A—F不区分大小写 10转2:将这个数不断除以2,直到商为0,然后把每步得到的余数倒过来&#…

数据结构--链表进阶面试题

在链表题目开始之前我们来复习一道数组元素的逆序问题&#xff1a; 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 提示&#xff1a; 1 < nums.length < 10^5-2^31 < nums[i] < 2^31 - 10 < k < 10^5 思…

AlphaFold3(AF3)简单介绍:预测各种生物分子结构和它们之间相互作用的深度学习模型

参考: 文章地址: https://www.nature.com/articles/s41586-024-07487-w https://blog.google/technology/ai/google-deepmind-isomorphic-alphafold-3-ai-model/ AlphaFold3体验官网: https://golgi.sandbox.google.com/ 《Accurate structure prediction of biomolecula…

分享一个php常驻内存多进程任务的扩展

前言 最近在摸鱼的时候发现一个PHP常驻内存多进程任务扩展包&#xff1a;EasyTask: PHP常驻内存多进程任务管理器&#xff0c;支持定时任务(PHP resident memory multi-process task manager, supports timing tasks) (gitee.com)&#xff0c;支持php使用多线程处理任务。之前…

文心一言 VS 讯飞星火 VS chatgpt (252)-- 算法导论18.2 5题

五、因为叶结点无需指向孩子结点的指针&#xff0c;那么对同样大小的磁盘页面&#xff0c;可选用一个与内部结点不同的(更大的) t 值。请说明如何修改 B 树的创建和插人过程来处理这个变化。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 当我们在B树&#xff…

Kafk设计篇01(设计动机+持久化)

背景 本篇文章基于最新版本&#xff1a;kafka 3.7&#xff0c;其他版本的设计&#xff0c;请参考官网&#xff1a; https://kafka.apache.org/documentation/设计动机 任何组件都有它存在的必要&#xff0c;必然是要解决某一类问题的。我们来看看kafka设计的初衷如何。 kaf…

Python---Numpy万字总结(1)

NumPy的应用&#xff08;1&#xff09; Numpy 是一个开源的 Python 科学计算库&#xff0c;用于快速处理任意维度的数组。Numpy 支持常见的数组和矩阵操作&#xff0c;对于同样的数值计算任务&#xff0c;使用 NumPy 代码简洁&#xff0c;在性能上也远远优于原生 Python&#…
最新文章