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

小白学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等动态脚本语言不同&#xff0c;Go语言沿袭了静态编译型语言的传统&#xff1a;使用变量之前需要先进行变量的声明。 变量声明形式使用决策流程图 这里大致列一下Go语言常见的变量声明形式&#xff1a; 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双线协议&#xff0c;需要重新配置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&#xff0c;那么Shader是个什么概念呢&#xff1f;其实对于开发同事来说还是比较难理解的&#xff0c;一般来说Shader是服务于图形渲染的一类技术&#xff0c;开发人员可以通过其shader语言来自定义显卡渲染页面的算法&#xff0…...

苹果电脑要安装杀毒软件吗?mac用什么杀毒软件好?

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

MySQL——索引

索引在 MySQL 数据库中分三类&#xff1a; B 树索引Hash 索引全文索引 目的&#xff1a;在查询的时候提升效率 b树 参考&#xff1a;https://blog.csdn.net/qq_40649503/article/details/115799935 数据库索引&#xff0c;是数据库管理系统中一个排序的数据结构&#xf…...

110. 平衡二叉树

题目链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 递归法&#xff1a; 我的代码&#xff1a; *** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* Tree…...

遗忘因子递推最小二乘参数估计(FFRLS)

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

【redis进阶】基础知识简要回顾

1. 常见功能介绍 聚合统计 使用list集合的差集、并集来统计 排序统计 SortedSet&#xff08;ZSet&#xff09;统计&#xff0c;再利用分页列出权重高的元素 二值状态统计 BitMap存储&#xff0c;获取并统计 SETBIT uid:sign:3000:202008 2 1 GETBIT uid:sign:3000:202008 2…...

HTML5-3-表格

文章目录 属性边框属性标题跨行和跨列单元格边距 HTML 表格由 <table> 标签来定义。 tr&#xff1a;tr 是 table row 的缩写&#xff0c;表示表格的一行。td&#xff1a;td 是 table data 的缩写&#xff0c;表示表格的数据单元格。th&#xff1a;th 是 table header的缩…...

Spring Boot + Vue的前后端项目结构及联调查询

Spring Boot Vue的前后端项目结构及联调查询 当你刚开始学习前后端开发时&#xff0c;可能会感到有些困惑和不知所措。下面是一些建议&#xff0c;希望能为你的学习之旅提供一些启示&#xff1a; 建立坚实的基础知识&#xff1a;学习前后端开发的第一步是建立坚实的基础知识。…...

Transformer貌似也是可以使用state递归解码和训练的

import paddle import numpy as npclass HeadLoss(paddle.nn.Layer):def __init__(self):super(HeadLoss, self).__init__()...

振弦采集仪应用地铁隧道安全监测详细解决方案

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

2023 IntelliJ IDEA下载、安装教程, 附详细图解

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

波卡生态重要动态一览:w3ndi 推出,首尔、新加坡、里斯本活动接踵而至

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

成都瀚网科技有限公司:抖音商家怎么免费入驻?

随着抖音成为全球最受欢迎的短视频平台之一&#xff0c;越来越多的商家开始关注抖音上的商机。抖音商家的进驻可以帮助商家扩大品牌影响力和销售渠道。那么&#xff0c;如何免费进入抖音成为商家呢&#xff1f;下面就为大家介绍一下具体步骤。 1、抖音商家如何免费注册&#xf…...

vue Router从入门到精通

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

【100天精通Python】Day56:Python 数据分析_Pandas数据清洗和处理(删除填充插值,数据类型转换,去重,连接与合并)

目录 数据清洗和处理 1.处理缺失值 1.1 删除缺失值&#xff1a; 1.2 填充缺失值&#xff1a; 1.3 插值&#xff1a; 2 数据类型转换 2.1 数据类型转换 2.2 日期和时间的转换&#xff1a; 2.3 分类数据的转换&#xff1a; 2.4 自定义数据类型的转换&#xff1a; 3 数…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...