Go 你不知道的简短变量声明约束
前言
虽然简短变量声明这个语法糖用起来很方便,但有时也会给你一个意外也可能带你掉入陷阱。
我曾因滥用这个:=
语法糖,发生过一次故障,所以才认真研究了一下它的原理和规则,大家可以做为参考。
规则
规则一: 多变量赋值可能会重新声明
我们知道使用:=
一次可以声明多个变量,像下面这样:
field1, offset := nextField(str, 0)
上面代码定义了两个变量,并用函数返回值进行赋值。
如果这两个变量中的一个再次出现在:=
左侧就会重新声明。像下面这样:
field1, offset := nextField(str, 0) field2, offset := nextField(str, offset)
offset被重新声明。
重新声明并没有什么问题,它并没有引入新的变量,只是把变量的值改变了,但要明白,这是Go提供的一个语法糖。
- 当
:=
左侧存在新变量时(如field2),那么已声明的变量(如offset)则会被重新声明,不会有其他额外副作用。 - 当
:=
左侧没有新变量是不允许的,编译会提示no new variable on left side of :=
。
我们所说的重新声明不会引入问题要满足一个前提,变量声明要在同一个作用域中出现。如果出现在不同的作用域,那很可能就创建了新的同名变量,同一函数不同作用域的同名变量往往不是预期做法,很容易引入缺陷。关于作用域的这个问题,我们在本节后面介绍。
规则二:不能用于函数外部
简短变量场景只能用于函数中,使用:=
来声明和初始化全局变量是行不通的。
比如,像下面这样:
package sugar import fmt rule := "Short variable declarations" // syntax error: non-declaration statement outside function body
这里的编译错误提示syntax error: non-declaration statement outside function body
,表示非声明语句不能出现在函数外部。可以理解成:=
实际上会拆分成两个语句,即声明和赋值。赋值语句不能出现在函数外部的。
变量作用域问题
几乎所有的工程师都了解变量作用域,但是由于:=
使用过于频繁的话,还是有可能掉进陷阱里。
下面代码源自真实项目,但为了描述方便,也为了避免信息安全风险,简化如下:
func Redeclare() { field, err:= nextField() // 1号err if field == 1{ field, err:= nextField() // 2号err newField, err := nextField() // 3号err ... } ... }
注意上面声明的三个err变量。 2号err与1号err不属于同一个作用域,:=
声明了新的变量,所以2号err与1号err属于两个变量。 2号err与3号err属于同一个作用域,:=
重新声明了err但没创建新的变量,所以2号err与3号err是同一个变量。
如果误把2号err与1号err混淆,就很容易产生意想不到的错误。
赠人玫瑰手留余香,如果觉得不错请给个赞~
本篇文章已归档到GitHub项目,求星~ 点我即达

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
禁止Golang编译时“imported and not used”和“declared and not used”两种报错
Go语言在代码规范之严格是有目共睹的,引用未使用的头文件会报“imported and not used”错误,定义未使用的变量会报“declared and not used”错误。因为golang编译器只有错误没有报警,所以代码中如果有此类问题,编译就会停止。 Golang不提供语法宽容的debug模式,也就是说,无论是什么时候,Go代码都必须保持干干净净的状态。 随手注释部分变量是编码阶段的一个常用手段,Golang的编译器每每跳出来,让你把变量的定义和相关头文件的引用也通通删掉。有时候临时注释一段代码会产生一堆未引用和未定义错误,而为了解决这些错误往往又会把代码被改得面目全非。对于debug阶段的程序员来讲,有一个管得太宽的编译器是一件痛苦的事情。 好在Golang是开源的,弄一个不太折腾的Golang编译器并不困难。 修改源码 首先下载golang代码: $ git clone https://github.com/golang/go 拉到最新分支,现在最新的版本号是1.12.5: $ cd go $ git checkout -b debug-1.12.5 go1.12.5...
- 下一篇
【AI实战】手把手教你实现文字识别模型(入门篇:验证码识别)
文字识别在现实生活中有着非常重要的应用,主要由文字检测、内容识别两个关键步骤组成,在本博客之前的文章中已介绍了文字检测、内容识别的经典模型原理(见文章:大话文本检测经典模型:CTPN , 大话文本识别经典模型:CRNN),本文主要从实战的角度介绍如何实现文字识别模型。 在之前的文章中,已经介绍过了跟文字识别相关的实战内容:基于MNIST数据集识别手写数字的实战内容(见文章:训练你的第一个AI模型:MNIST手写数字识别模型),这个相对简单。今天再介绍文字识别的另一个经典应用:验证码识别,作为文字识别的实战入门篇。 验证码在手机APP、WEB网站中非常普遍,主要是为了防止恶意登录、刷票、灌水、爬虫等异常行为,也可能是为了缓解系统的后台压力(例如在秒杀、抢票时,强制要求输入验证码)。本文主要介绍文本型验证码的识别,文本型验证码由数字、英文大小写字母,甚至中文随机组成,再进行变形扭曲、加干扰线、加背景噪音等操作,主要是为了防止被光学字符识别(OCR)之类的程序自动识别出图片上的文字而失去效果,如下图: 由于存在着比较强的干扰信息,因此,直接使用OCR进行识别,效果很不理想,而通过AI可很好...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,CentOS8安装Elasticsearch6.8.6
- 2048小游戏-低调大师作品
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2全家桶,快速入门学习开发网站教程