Go语言开发小技巧易错点100例(十四)

往期回顾:

  • Go语言开发小技巧&易错点100例(一)
  • Go语言开发小技巧&易错点100例(二)
  • Go语言开发小技巧&易错点100例(三)
  • Go语言开发小技巧&易错点100例(四)
  • Go语言开发小技巧&易错点100例(五)
  • Go语言开发小技巧&易错点100例(六)
  • Go语言开发小技巧&易错点100例(七)
  • Go语言开发小技巧&易错点100例(八)
  • Go语言开发小技巧&易错点100例(九)
  • Go语言开发小技巧&易错点100例(十)
  • Go语言开发小技巧&易错点100例(十一)
  • Go语言开发小技巧&易错点100例(十二)
  • Go语言开发小技巧&易错点100例(十三)

本期看点(技巧类用【技】表示,易错点用【易】表示)

  • init函数的执行机制【易】

  • sync.Once同步【技】

  • Go进行小数的运算【技】

正文开始:

init()函数的执行机制

在Go语言中,init函数是用于初始化包或模块的特殊函数。它们会在程序开始执行任何用户定义的函数之前自动调用。Go语言运行时系统会保证在程序开始执行main函数之前,所有包的init函数都会被调用。但是,具体的调用顺序依赖于包之间的依赖关系。

  • 如果包A依赖于包B(例如,包A导入了包B),那么包B的init函数会在包A的init函数之前执行。
  • 如果包A和包B都不依赖于对方,但是它们都被main包所依赖,那么它们的init函数将按照编译器的内部顺序执行,这通常与它们在文件系统中的顺序有关,但并不严格保证。

我们来做一下试验:

main包

package mainimport ("fmt""go-init/db"
)func init() {fmt.Println("package main init() func ...")
}func main() {db.LoadModel() //顺序调换还是限制性另一个文件的init函数db.LoadConfig()fmt.Println("package main main() func ...")
}

db包config.go:

package dbimport "fmt"func init() {fmt.Println("package db init() func ...")
}func LoadConfig() {fmt.Println("package db LoadConfig() func ...")
}

db包model.go:

package dbimport "fmt"func init() {fmt.Println("package db other init() func ...")
}func LoadModel() {fmt.Println("package db LoadModel() func ...")
}

执行main函数:

package db init() func ...
package db other init() func ...
package main init() func ...
package db LoadModel() func ...
package db LoadConfig() func ...
package main main() func ...

由上面的代码我们可知,优先级关系为:依赖包的init函数 > 其他包的init函数 > main包的init函数 > main函数

总的来说,虽然你不能直接控制init函数的执行顺序,但你可以通过控制包的依赖关系来间接地影响它们。如果需要对初始化顺序有严格的控制,通常最好的做法是使用显式的初始化函数,并在main函数中或在某个特定init函数中调用它们,以确保正确的执行顺序。

sync.Once同步

在Go语言中,sync.Once 是一个用于确保某个操作只执行一次的同步原语。它提供了一种机制,可以在多线程或多协程环境下安全地执行初始化操作,而无需担心重复执行或竞态条件。

sync.Once 结构体有一个未导出的字段,用于跟踪操作是否已经被执行过。它提供了一个 Do 方法,该方法接受一个函数作为参数,并确保该函数只被调用一次,不论 Do 被调用多少次。

下面是 sync.Once 的基本用法:

package mainimport ("fmt""sync"
)func main() {var once sync.Once// 定义一个初始化函数initFunc := func() {fmt.Println("Initialization function is called only once.")}// 模拟多个协程尝试调用初始化函数for i := 0; i < 5; i++ {go once.Do(initFunc)}// 等待所有协程执行完毕var wg sync.WaitGroupwg.Add(5)for i := 0; i < 5; i++ {go func() {defer wg.Done()once.Do(initFunc)}()}wg.Wait()
}

在上面的例子中,尽管我们多次调用 once.Do(initFunc),但 initFunc 函数只会被执行一次。这是通过 sync.Once 的内部同步机制实现的,它确保了 Do 方法内部的函数只会在第一次调用时执行。

sync.Once 在多种场景下都非常有用,尤其是在需要执行一些只需要初始化一次的资源加载、配置设置或全局状态设置时。由于它保证了操作的原子性,因此在并发编程中特别有用。

需要注意的是,sync.Once 只能确保某个操作执行一次,而不是确保某个状态只被设置一次。如果你需要在多次调用之间保持某个状态,你可能需要使用其他同步机制,比如互斥锁(sync.Mutex)或原子操作(sync/atomic 包)。

Go进行保留小数的运算

有时候在项目中涉及到Go语言保留小数运算的时候经常会弄不清,比如两个int32类型的值进行除法保留小数或者具体到保留两位小数,int32类型和float32类型进行乘除保留小数等,下面有几个简单的例子,展示了如何在Go中进行小数运算:

两个float64类型进行运算:

package mainimport ("fmt""math"
)func main() {// 定义两个float64类型的小数a := 3.14b := 2.71// 乘法product := a * bfmt.Printf("Product: %f\n", product)// 除法quotient := a / bfmt.Printf("Quotient: %f\n", quotient)
}

有两个int32类型进行除法运算,同时保留两位小数:

package mainimport ("fmt"
)func main() {// 定义两个int32类型的变量a := int32(10)b := int32(3)// 将它们转换为float64类型以执行除法运算result := float64(a) / float64(b)// 使用fmt.Printf格式化输出,保留两位小数fmt.Printf("Result: %.2f\n", result)
}

一个int32类型的变量和一个float32类型的变量除法运算同时保留两位小数:

package mainimport ("fmt"
)func main() {// 定义一个int32类型的变量和一个float32类型的变量a := int32(10)b := float32(3.0)// 将int32变量转换为float32类型以执行除法运算result := float32(a) / b// 使用fmt.Printf格式化输出,保留两位小数fmt.Printf("Result: %.2f\n", float64(result)) // 注意:将float32转换为float64以正确格式化输出
}

完结~

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

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

相关文章

贪心算法|452.用最少数量的箭引爆气球

力扣题目链接 class Solution { private:static bool cmp(const vector<int>& a, const vector<int>& b) {return a[0] < b[0];} public:int findMinArrowShots(vector<vector<int>>& points) {if (points.size() 0) return 0;sort(p…

rk3588开发板上安装ssh服务

目的&#xff1a;实现远程访问和控制&#xff0c;其他主机远程控制rk3588 方法及操作步骤&#xff1a; 1&#xff09;安装&#xff1a;sudo apt install openssh-server 2&#xff09; 查看运行状态 sudo systemctl status ssh 其它主机远程连接该开发板的ip和端口22即可

urwid,一个好用的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个好用的 Python 库 - urwid。 Github地址&#xff1a;https://github.com/urwid/urwid Urwid 是一个功能强大的 Python 库&#xff0c;用于创建基于文本的用户界面&#xf…

[23年蓝桥杯H题] 合并石子

问题描述 在桌面从左至右横向摆放着 N 堆石子。每一堆石子都有着相同的颜色&#xff0c;颜 色可能是颜色 0 &#xff0c;颜色 1 或者颜色 2 中的其中一种。 现在要对石子进行合并&#xff0c;规定每次只能选择位置相邻并且颜色相同的两堆 石子进行合并。合并后新堆的相对位置保…

试除法求素数

目录 一、题目 描述 输入描述&#xff1a; 输出描述&#xff1a; 示例1 二、结论 三、代码 四、讲解 五、注意点&#xff1a; 一、题目 描述 输入M、N&#xff0c;1 < M < N < 1000000&#xff0c;求区间[M,N]内的所有素数的个数。素数定义&#xff1a;除了1以…

设计模式(015)行为型之模板方法模式

模板方法模式&#xff0c;它定义了一个算法的骨架&#xff0c;将一些步骤延迟到子类中实现。这个模式允许子类重新定义算法的某些步骤&#xff0c;而不改变算法的结构。通常&#xff0c;模板方法由一个抽象类实现&#xff0c;其中包含算法的基本步骤&#xff0c;并且这些步骤可…

常用的启发式算法

常用的启发式算法 引言&#xff1a;一、启发式算法概述&#xff1a;二、常用的启发式算法&#xff1a;三、启发式算法的选择与应用&#xff1a;四、总结&#xff1a; 引言&#xff1a; 在计算机科学和人工智能领域&#xff0c;启发式算法是一类用于解决优化问题的算法。它们通…

unipush+个推实现消息推送

1.注册个推平台的帐号个推&#xff0c;专业的数据智能服务商-为垂直领域提供数据智能解决方案 2.应用列表中选择新增应用/服务 3.填写下应用信息4.创建好应用后在manifest.json中的sdkConfigs配置上写入appid、appkey、appsecret "sdkConfigs" : {"ad" :…

c++关键字: =delete和=default

delete 概述 delete关键字是c11新增的关键字&#xff0c;主要用于的场景是&#xff1a;当我们不希望类中的函数被类对象在外部调用的时候&#xff0c;我们就可以使用这个关键字。 其实&#xff0c;之前我们实现这种功能是将这些函数放在private修饰符下&#xff0c;但是这种方…

【Keil5-Boot和APP配置】

Keil5-Boot和App配置 ■ Keil5-Boot和APP配置■ 一&#xff1a;sct文件 sct文件配置■ 二&#xff1a;发布版本不需要在 C/C&#xff0c;Asm&#xff0c;Linker&#xff0c;中添加 CMDDEBUG 宏定义。■ 三&#xff1a;Debug版本需要在Linker添加 --pd"-DCMDDEBUG" 才…

windows版本-idea中下载的java版本在哪

1、点击idea的file-projectStructure 进入&#xff1a; 通过电脑目录进入该目录 找到bin目录&#xff0c;copy该目录地址 copy下来之后设置到系统环境变量中

脑电放大 LM386

LM386介绍 LM386 是一种音频集成功放&#xff0c;具有自身功耗低、电压增益可调整电源电压范围大、外接元件少和总谐波失真小等优点&#xff0c;广泛应用于录音机和收音机之中。 电源电压 4-12V 或 5-18V(LM386N-4);静态消耗电流为 4mA;电压增益为20-200dB;在引脚1和8开路时&a…

scan纯享代码 java

scan纯享代码 java 1 scan用法2 next3 nextLine 1 scan用法 在录入中间有回车的字符串的时候&#xff0c;不要使用next&#xff08;&#xff09;和nextLine&#xff08;&#xff09;的配合&#xff01;&#xff01; scan用法 Scanner scannernew Scanner(System.in); String…

【S32K3 MCAL配置】-3.2-CANFD配置-发送“经典CAN/CANFD标准帧“和“经典CAN/CANFD扩展帧“(基于MCAL+FreeRTOS)

"><--返回「Autosar_MCAL高阶配置」专栏主页--> 目录 实现的架构:基于MCAL层 前期准备工作: 1 评估板S32K312EVB-Q172中CAN外设

【通信原理笔记】【三】模拟信号调制——3.5 角度调制(FM、PM)与其频谱特性

文章目录 前言一、相位与频率二、PM和FM的数学表示三、FM的频谱四、FM信号的带宽——卡松公式总结 前言 在之前介绍的几种调制方式中&#xff0c;我提到信噪比时计算的是用户解调后的信噪比&#xff0c;然而在北邮通信原理课中考虑的是解调器输入的信噪比&#xff0c;即考虑的…

python 图片 中文识别 pytesseract

python 图片 中文识别 pytesseract 参考链接 https://blog.csdn.net/weixin_47754149/article/details/125651707 微信 中 长截图&#xff0c;然后传到 电脑上面 安装 方法 https://digi.bib.uni-mannheim.de/tesseract/ tesseract-ocr-w64-setup-5.3.3.20231005.exe 安装的…

备战蓝桥杯(java)(日益更新)

备战蓝桥杯&#xff08;java&#xff09;&#xff08;日益更新&#xff09; 文章目录 备战蓝桥杯&#xff08;java&#xff09;&#xff08;日益更新&#xff09;前言&#xff1a;一、c 到 java 须要注意的地方&#xff1a;二、多练java代码&#xff1a;&#xff08;用java代码…

linux常用目录结构(目录命令)--6986字详谈

前面与大家讨论了linux的发展与由来&#xff08;这一块挺多的&#xff0c;小编还没有编写完成&#xff0c;希望大家理解&#xff09;&#xff0c;紧接着谈到了vmware安装及运行所存在的故障&#xff08;鉴定错误&#xff0c;虚拟机没有网&#xff0c;蓝屏等常见现象的总结及处理…

【vim 学习系列文章 20 -- a:mode 的值有哪些?】

请阅读【嵌入式开发学习必备专栏 之 Vim】 文章目录 a:mode 的值有哪些?举例Vim 底部状态栏设置 a:mode 的值有哪些? 在 Vim 脚本语言中&#xff0c;a:mode 常常用于函数内部&#xff0c;以获取该函数被调用时 Vim 正处于的模式。它主常用于那些可以从不同模式下被调用的函数…

what is tty?

waht is tty? 黑话&#xff1a;TTY 为什么使用Linux的时候CtrlC就会终止一个命令运行,ta是如何设置的? stty -a 桌面切换 CTRL ALT F1 – 锁屏 CTRL ALT F2 – 桌面环境 CTRL ALT F3 – TTY3 CTRL ALT F4 – TTY4 CTRL ALT F5 – TTY5 CTRL ALT F6 – TTY6