小白学go基础05-变量声明形式
和Python、Ruby等动态脚本语言不同,Go语言沿袭了静态编译型语言的传统:使用变量之前需要先进行变量的声明。
变量声明形式使用决策流程图
这里大致列一下Go语言常见的变量声明形式:
var a int32
var s string = "hello"
var i = 13
n := 17
var (
crlf = []byte("\r\n")
colonSpace = []byte(": ")
)
如果让Go语言的设计者重新设计一次变量声明语法,相信他们很大可能不会再给予Gopher这么大的变量声明灵活性,但目前这一切都无法改变。对于以面向工程著称且以解决规模化问题为目标的Go语言,Gopher在变量声明形式的选择上应尽量保持项目范围内一致。
Go语言有两类变量。
● 包级变量(package variable
):在package级别可见的变量。如果是导出变量,则该包级变量也可以被视为全局变量。
● 局部变量(local variable)
:函数或方法体内声明的变量,仅在函数或方法体内可见。
下面来分别说明实现这两类变量在声明形式选择上保持一致性的一些最佳实践。
包级变量的声明形式
包级变量只能使用带有var关键字的变量声明形式,但在形式细节上仍有一定的灵活度。我们从声明变量时是否延迟初始化这个角度对包级变量进行一次分类。
1. 声明并同时显式初始化
下面是摘自Go标准库中的代码(Go 1.12):
// $GOROOT/src/io/pipe.go
var ErrClosedPipe = errors.New("io: read/write on closed pipe")// $GOROOT/src/io/io.go
var EOF = errors.New("EOF")
var ErrShortWrite = errors.New("short write")
我们看到,对于在声明变量的同时进行显式初始化的这类包级变量,实践中多使用下面的格式:
var variableName = InitExpression
Go编译器会自动根据等号右侧的InitExpression表达式求值的类型确定左侧所声明变量的类型。
如果InitExpression采用的是不带有类型信息的常量表达式,比如下面的语句:
var a = 17
var f = 3.14
则包级变量会被设置为常量表达式的默认类型:以整型值初始化的变量a,Go编译器会将之设置为默认类型int;而以浮点值初始化的变量f,Go编译器会将之设置为默认类型float64。
如果不接受默认类型,而是要显式为包级变量a和f指定类型,那么有以下两种声明方式:
// 第一种
var a int32 = 17
var f float32 = 3.14
// 第二种
var a = int32(17)
var f = float32(3.14)
从声明一致性的角度出发,Go语言官方更推荐后者,这样就统一了接受默认类型和显式指定类型两种声明形式。尤其是在将这些变量放在一个var块中声明时,我们更青睐这样的形式:
var (
a = 17
f = float32(3.14)
)
而不是下面这种看起来不一致的声明形式:
var (
a = 17
f float32 = 3.14
)
2. 声明但延迟初始化
对于声明时并不显式初始化的包级变量,我们使用最基本的声明形式:
var a int32
var f float64
虽然没有显式初始化,但Go语言会让这些变量拥有初始的“零值”。如果是自定义的类型,保证其零值可用是非常必要的,这一点将在后文中详细说明。
3. 声明聚类与就近原则
Go语言提供var块用于将多个变量声明语句放在一起,并且在语法上不会限制放置在var块中的声明类型。
但是我们一般将同一类的变量声明放在一个var块中,将不同类的声
明放在不同的var块中;或者将延迟初始化的变量声明放在一个var块,而将声明并显式初始化的变量放在另一个var块中,称之为“声明聚类”。
比如下面Go标准库中的代码:
// $GOROOT/src/net/http/server.go
var (
bufioReaderPool sync.Pool
bufioWriter2kPool sync.Pool
bufioWriter4kPool sync.Pool
)
var copyBufPool = sync.Pool {
New: func() interface{} {
b := make([]byte, 32*1024)
return &b
},
}
...
// $GOROOT/src/net/net.go
var (
aLongTimeAgo = time.Unix(1, 0)
noDeadline = time.Time{}
noCancel = (chan struct{})(nil)
)
var threadLimit chan struct{}
...
我们看到在server.go中,copyBufPool变量没有被放入var块中,因为它的声明带有显式初始化,而var块中的变量声明都是延迟初始化的;
net.go中的threadLimit被单独放在var块外面,一方面是考虑它是延迟初始化的变量声明,另一方面是考虑threadLimit在含义上与var块中标识时间限制的变量有所不同。
局部变量的声明形式
1. 对于延迟初始化的局部变量声明,采用带有var关键字的声明形式
比如标准库strings包中byteReplacer的方法Replace中的变量buf:
// $GOROOT/src/strings/replace.go
func (r *byteReplacer) Replace(s string) string {
var buf []byte // 延迟分配
for i := 0; i < len(s); i++ {
b := s[i]
if r[b] != b {
if buf == nil {
buf = []byte(s)
}
buf[i] = r[b]
}
}
if buf == nil {
return s
}
return string(buf)
}
另一种常见的采用带var关键字声明形式的变量是error类型的变量err(将error类型变量实例命名为err也是Go的一个惯用法),尤其是当defer后接的闭包函数需要使用err判断函数/方法退出状态时。示例代码如下:
func Foo() {
var err error
defer func() {
if err != nil {
...
}
}()
err = Bar()
...
}
2. 对于声明且显式初始化的局部变量,建议使用短变量声明形式
短变量声明形式是局部变量最常用的声明形式,它遍布Go标准库代码。对于接受默认类型的变量,可以使用下面的形式:
a := 17
f := 3.14
s := "hello, gopher!"
3. 尽量在分支控制时应用短变量声明形式
这应该是Go中短变量声明形式应用最广泛的场景了。在编写Go代码时,我们很少单独声明在分支控制语句中使用的变量,而是通过短变量声明形式将其与if、for等融合在一起,就像下面这样:
// $GOROOT/src/net/net.go
func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
// 笔者注:在if循环控制语句中使用短变量声明形式
if wv, ok := w.(buffersWriter); ok {
return wv.writeBuffers(v)
}
// 笔者注:在for条件控制语句中使用短变量声明形式
for _, b := range *v {
nb, err := w.Write(b)
n += int64(nb)
if err != nil {
v.consume(n)
return n, err
}
}
v.consume(n)
return n, nil
}
这样的应用方式体现出“就近原则”,让变量的作用域最小化了。
想做好代码中变量声明的一致性,需要明确要声明的变量是包
级变量还是局部变量、是否要延迟初始化、是否接受默认类型、是否为分支控制变量,并结合聚类和就近原则。
相关文章:

小白学go基础05-变量声明形式
和Python、Ruby等动态脚本语言不同,Go语言沿袭了静态编译型语言的传统:使用变量之前需要先进行变量的声明。 变量声明形式使用决策流程图 这里大致列一下Go语言常见的变量声明形式: var a int32 var s string "hello" var i 13 …...

高可用Kuberbetes部署Prometheus + Grafana
概述 阅读官方文档部署部署Prometheus Grafana GitHub - prometheus-operator/kube-prometheus at release-0.10 环境 步骤 下周官方github仓库 git clone https://github.com/prometheus-operator/kube-prometheus.git git checkout release-0.10 进入工作目录 cd kube…...

ardupilot 安装gcc-arm-none-eabi编译工具
目录 文章目录 目录摘要0简介1.下载网站2.安装摘要 本节主要记录ardupilot使用的编译器安装过程。 0简介 gcc-arm-none-eabi是GNU项目下的软件,是一个面向裸机arm的编译器。那么说了这么多介绍,它都包含什么具体功能又怎么安装与使用呢,我们继续。 1.下载网站 gcc-arm-n…...
ORACLE集群管理-19C RAC重新配置IPV6
1 问题概述 数据库已经配置和IPV6和 IPV4双线协议,需要重新配置IPV6 2 关闭相关资源 1 root用户执行 ./srvctl stop scan_listener -i 1 ./srvctl stop scan ./srvctl stop listener -n orcldb1 ./srvctl stop listener -n orcldb2 ./srvctl stop vip -n orcldb…...

Mybatis实体类属性与数据库字段的对应关系
方法一:起别名 select t_id(数据库字段) tId(类的属性), ... , ...from 表名 方法二:开启驼峰映射 <!-- 开启驼峰映射 数据库 s_id java类 sId--><setting name"mapUnderscoreToCamelCase" value"true"/> 当java类中属性命名…...

Unity(三) Shader着色器初探
学习3D开发技术的时候无可避免的要接触到Shader,那么Shader是个什么概念呢?其实对于开发同事来说还是比较难理解的,一般来说Shader是服务于图形渲染的一类技术,开发人员可以通过其shader语言来自定义显卡渲染页面的算法࿰…...

苹果电脑要安装杀毒软件吗?mac用什么杀毒软件好?
对于这个问题让人很是纠结,Mac不需要杀毒这个理论一直都深入人心,Mac OS X权限管理特性可以防毒的说法也一直甚嚣尘上,很多小伙伴如我一样搞不清楚到底要不要安装杀毒软件。,毕竟当前个人信息安全泄露泛滥不穷的年代,我…...

MySQL——索引
索引在 MySQL 数据库中分三类: B 树索引Hash 索引全文索引 目的:在查询的时候提升效率 b树 参考:https://blog.csdn.net/qq_40649503/article/details/115799935 数据库索引,是数据库管理系统中一个排序的数据结构…...
110. 平衡二叉树
题目链接: 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 递归法: 我的代码: *** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* Tree…...

遗忘因子递推最小二乘参数估计(FFRLS)
基于遗忘因子的最小二乘法电池参数辨识 最小二乘法是系统辨识中最常用的一种估算方法。为了克服最小二乘法存在”数据饱和”的问题,我们通常采用含有遗忘因子的递推最小二乘法(Forgetting Factor Recursive Least Square,FFRLS)算法进行电池模型的参数辨识。 1、二…...

【redis进阶】基础知识简要回顾
1. 常见功能介绍 聚合统计 使用list集合的差集、并集来统计 排序统计 SortedSet(ZSet)统计,再利用分页列出权重高的元素 二值状态统计 BitMap存储,获取并统计 SETBIT uid:sign:3000:202008 2 1 GETBIT uid:sign:3000:202008 2…...

HTML5-3-表格
文章目录 属性边框属性标题跨行和跨列单元格边距 HTML 表格由 <table> 标签来定义。 tr:tr 是 table row 的缩写,表示表格的一行。td:td 是 table data 的缩写,表示表格的数据单元格。th:th 是 table header的缩…...
Spring Boot + Vue的前后端项目结构及联调查询
Spring Boot Vue的前后端项目结构及联调查询 当你刚开始学习前后端开发时,可能会感到有些困惑和不知所措。下面是一些建议,希望能为你的学习之旅提供一些启示: 建立坚实的基础知识:学习前后端开发的第一步是建立坚实的基础知识。…...
Transformer貌似也是可以使用state递归解码和训练的
import paddle import numpy as npclass HeadLoss(paddle.nn.Layer):def __init__(self):super(HeadLoss, self).__init__()...

振弦采集仪应用地铁隧道安全监测详细解决方案
振弦采集仪应用地铁隧道安全监测详细解决方案 随着城市化进程的不断加快,地铁作为一种高效、便捷、环保的交通方式已经成为现代城市不可或缺的一部分。因此,对地铁的安全性也越来越重视,一般二三线以上的城市在不断发展中,地铁做…...

2023 IntelliJ IDEA下载、安装教程, 附详细图解
文章目录 下载与安装IDEA推荐阅读 下载与安装IDEA 首先先到官网下载最新版的IntelliJ IDEA, 下载后傻瓜式安装就好了 官网下载地址:https://www.jetbrains.com/ 1、下载完后在本地找到该文件,双击运行 idea 安装程序 2、点击 Next 3、选择安装路径&…...

波卡生态重要动态一览:w3ndi 推出,首尔、新加坡、里斯本活动接踵而至
Web3 市场冷却,但新的社区合作与推进仍在发生,技术和产品依然不断迭代。OneBlock 为你介绍波卡生态近期值得你关注的动态,以及接下来重要的行业活动。 波卡生态重要进展 1、最新 Referendum#110,提议对验证器配置进行多项修改&a…...

成都瀚网科技有限公司:抖音商家怎么免费入驻?
随着抖音成为全球最受欢迎的短视频平台之一,越来越多的商家开始关注抖音上的商机。抖音商家的进驻可以帮助商家扩大品牌影响力和销售渠道。那么,如何免费进入抖音成为商家呢?下面就为大家介绍一下具体步骤。 1、抖音商家如何免费注册…...

vue Router从入门到精通
文章目录 介绍使用多级路由实例 路由的query参数传递参数接收参数实例 命名路由作用使用 params参数声明接收params参数传参接收参数实例 props配置实例 router-link的replace属性编程式路由导航作用使用实例 缓存路由组件两个新的生命周期钩子实例 路由守卫作用分类全局守卫独…...

【100天精通Python】Day56:Python 数据分析_Pandas数据清洗和处理(删除填充插值,数据类型转换,去重,连接与合并)
目录 数据清洗和处理 1.处理缺失值 1.1 删除缺失值: 1.2 填充缺失值: 1.3 插值: 2 数据类型转换 2.1 数据类型转换 2.2 日期和时间的转换: 2.3 分类数据的转换: 2.4 自定义数据类型的转换: 3 数…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...