Golang常用语法糖
1、名字由来
语法糖(Syntactic sugar)的概念是由英国计算机科学家彼得·兰丁提出的,用于表示编程语言中的某种类型的语法,这些语法不会影响功能,但使用起来却很方便。
语法糖,也称糖语法,这些语法不仅不会影响功能,编译后的结果跟不使用语法糖也一样。
语法糖,有可能让代码编写变得简单,也有可能让代码可读性更高,但有时也会给你一个意外,也可能带你掉入陷阱让您的代码出问题。本文将讲解Golang常用语法糖。
2、Golang常用语法糖
2.1 简短变量声明 :=
规则:简短变量声明符这个语法糖使用起来很方便,导致你可能随手就会使用它定义一个变量,往往程序的bug就是随手写出来的,在这里说一下简短变量声明的原理和规则。
(1)多变量赋值可能会重新声明
使用 := 一次可以声明多个变量,例如:
i, j := 0, 0
j, k := 1, 1
- 当 := 左侧存在新的变量时(如 k),那么已经声明的变量(如 j)会被重新声明。这并没有引入新的变量,只是把变量的值改变了。
- 当 := 左侧没有新变量编译报错。如下示例由于左侧没有新变量编译会提示" No new variables on the left side of ':=' "错误。
i,j := 2,3
i,j := 6,8
(2)不能用于函数外部
:=这种简短变量声明只能用于函数中,用来初始化全局变量是不行的。可以理解成
:=会拆分成两个语句,即声明和赋值。赋值语句不能出现在函数外部的,因为在任何函数外,语句都应该以关键字开头,例如 type、var这样的关键字。
比如,像下面这样:
package sugar
import fmt rule := "Short variable declarations" // syntax error: non-declaration statement outside function body
这是因为在函数外部声明的变量是全局变量,它们具有包级别的作用域。在包级别作用域中,变量的声明通常是显式的,不需要使用短变量声明语法糖。而且在全局变量的声明中,必须指定变量的类型,这是因为编译器需要知道变量的大小和布局信息,以便在编译时为它们分配内存。
因此,如果要在包级别声明变量,需要使用 var 关键字或 const 关键字进行显式声明,不能使用 := 语法糖。例如:
package main import "fmt" // 使用 var 关键字显式声明全局变量
var globalVar = 10 func main() {
// 在函数内部使用 := 语法糖声明局部变量
localVar := 20
fmt.Println(globalVar, localVar)
}
总之,:= 只能用于局部变量的声明和初始化,而不能用于全局变量的声明和初始化,这是 Go 语言的语法规定。
(3)变量作用域问题
几乎所有的工程师都了解变量作用域,但是由于:=使用过于频繁的话,还是有可能掉进陷阱里。
下面代码源自真实项目,但为了描述方便,也为了避免信息安全风险,简化如下:
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混淆,就很容易产生意想不到的错误。
2.2 可变参函数 ...
我们先写一个可变参函数:
func Greeting(prefix string, who ...string) {
if who == nil {
fmt.Printf("Nobody to say hi.")
return
}
for _, people := range who{
fmt.Printf("%s %s\n", prefix, people)
}
}
Greeting函数负责给指定的人打招呼,其参数who为可变参数。这个函数几乎把可变参函数的特征全部表现出来了:
可变参数必须在函数参数列表的最后一个(否则会引起编译时歧义);
可变参数在函数内部是作为切片来解析的;
可变参数可以不填,不填时函数内部当成 nil 切片处理;
可变参数可以填入切片;
可变参数必须是相同类型的(如果需要是不同类型的可以定义为 interface{}类型);
(1)使用举例-不传值
调用可变参函数时,可变参部分是可以不传值的,例如:
func ExampleGreetingWithoutParameter() {
sugar.Greeting("nobody")
// OutPut:
// Nobody to say hi.
}
这里没有传递第二个参数。可变参数不传递的话,默认为nil。
(2)使用举例-传递多个参数
调用可变参函数时,可变参数部分可以传递多个值,例如:
func ExampleGreetingWithParameter() {
sugar.Greeting("hello:", "Joe", "Anna", "Eileen")
// OutPut:
// hello: Joe
// hello: Anna
// hello: Eileen
}
可变参数可以有多个。多个参数将会生成一个切片传入,函数内部按照切片来处理。
(3)使用举例-传递切片
调用可变参函数时,可变参数部分可以直接传递一个切片。参数部分需要使用slice...来表示切片。例如:
func ExampleGreetingWithSlice() {
guest := []string{"Joe", "Anna", "Eileen"}
sugar.Greeting("hello:", guest...)
// OutPut:
// hello: Joe
// hello: Anna
// hello: Eileen
}
此时需要注意的一点是,切片传入时不会生成新的切片,也就是说函数内部使用的切片与传入的切片共享相同的存储空间。说得再直白一点就是,如果函数内部修改了切片,可能会影响外部调用的函数。
2.3 new函数
在 Go 语言中,new 函数用于动态地分配内存,返回一个指向新分配的零值的指针。它的语法如下:
func new(Type) *Type
其中,Type 表示要分配的内存的类型,new 函数返回一个指向 Type 类型的新分配的零值的指针。但是需要注意的是,new 函数只分配内存,并返回指向新分配的零值的指针,而不会初始化该内存。
所谓零值,是指 Go 语言中变量在声明时自动赋予的默认值。对于基本类型来说,它们的零值如下:
- 布尔型:false
- 整型:0
- 浮点型:0.0
- 复数型:0 + 0i
- 字符串:""(空字符串)
- 指针:nil
- 接口:nil
- 切片、映射和通道:nil
因此,new 函数返回的指针指向新分配的零值,但不会将其初始化为非零值。如果需要将内存初始化为非零值,可以使用结构体字面量或者显式地为其赋值。例如:
package main
import "fmt"
type Person struct {
name string
age int
sex int
}
func main() {
// 使用 new 函数分配内存,但不会将其初始化为非零值
p := new(Person)
fmt.Println(p) // 输出:&{ 0 0}
// 使用结构体字面量初始化
p2 := &Person{name: "Tom", age: 18, sex: 1}
fmt.Println(p2) // 输出:&{Tom 18 1}
// 显式为字段赋值
p3 := new(Person)
p3.name = "Jerry"
p3.age = 20
p3.sex = 0
fmt.Println(p3) // 输出:&{Jerry 20 0}
}
上面的代码中,使用 new 函数分配了一个新的 Person 结构体,但不会将其初始化为非零值,因此输出结果是“空字符串 0 0”。接下来,使用结构体字面量或者显式为其赋值,将其初始化为非零值。
很明显,new函数的设计同样是为了方便程序员的使用。
Golang常用语法糖的更多相关文章
- vue 常用语法糖
//来自 https://www.cnblogs.com/lhl66/p/8021730.html 侵删 el:element 需要获取的元素,一定是HTML中的根容器元素 data:用于数据的存储 ...
- C#语法糖: 扩展方法(常用)
今天继续分享C#4.0语法糖的扩展方法,这个方法也是我本人比较喜欢的方法.大家先想想比如我们以前写的原始类型不能满足现在的需求,而需要在该类型中添加新的方法来实现时大家会怎么做.我先说一下我没有学习到 ...
- golang 赋值与声明语法糖使用注意事项
赋值与声明语法糖 基本用法略, 搜索即可 注意事项 类型推断 := 会自动进行类型推断, 当想要的类型不是自己想要的类型时需要进行类型转换 // i1 默认是 int 类型 i1 := 1 // 当需 ...
- ES5与ES6常用语法教程之 ②解构语法糖、声明变量异同
js常用语法系列教程如下 es5与es6常用语法教程(1) es5与es6常用语法教程(2) es5与es6常用语法教程(3) es5与es6常用语法教程(4) es5与es6常用语法教程(5) es ...
- C#语法糖,让编程更具乐趣
一.什么是语法糖 语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法 ...
- Java语法糖4:内部类
内部类 最后一个语法糖,讲讲内部类,内部类指的就是在一个类的内部再定义一个类. 内部类之所以也是语法糖,是因为它仅仅是一个编译时的概念,outer.java里面定义了一个内部类inner,一旦编译成功 ...
- using语法糖
资源的分类 首先说一下资源的分类: 托管资源:由CLR管理分配和释放资源 非托管资源:不受CLR管理的对象,如 文件(StreamReader,BinaryReader,DataTable,各种Str ...
- C# 基础小知识之yield 关键字 语法糖
原文地址:http://www.cnblogs.com/santian/p/4389675.html 对于yield关键字我们首先看一下msdn的解释: 如果你在语句中使用 yield 关键字,则意味 ...
- 转:【深入Java虚拟机】之六:Java语法糖
转载请注明出处:http://blog.csdn.net/ns_code/article/details/18011009 语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家P ...
- Vue01 Vue介绍、Vue使用、Vue实例的创建、数据绑定、Vue实例的生命周期、差值与表达式、指令与事件、语法糖
1 Vue介绍 1.1 官方介绍 vue是一个简单小巧的渐进式的技术栈,它提供了Web开发中常用的高级功能:视图和数据的解耦.组件的服用.路由.状态管理.虚拟DOM 说明:简单小巧 -> 压缩后 ...
随机推荐
- lnmp重新安装mysql
安装mysql好长时间,一直没去管,后来一直频繁重启,各种网上找方案去解决,最后问题太异常,一顿操作猛如虎之后把mysql彻底搞垮,无奈只能进行重装. whereis mysql mysql: /us ...
- JWT用户认证体系
依赖 <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifa ...
- c#调用键盘输入
[code]csharpcode: /// <summary> /// 键盘输入模拟 /// </summary> [DllImport("user32.dll&qu ...
- WordPress安全方案
一.WordPress介绍WordPress是一款世界级的网站内容管理系统,因其系统结构科学合理,功能强大,操作简单,拥有海量用户.和其他CMS一样,安全漏洞也是其无法避免的问题.虽然官方不断发布补丁 ...
- Python从零到壹丨详解图像平滑的两种非线性滤波方法
摘要:本文将详细讲解两种非线性滤波方法中值滤波和双边滤波. 本文分享自华为云社区<[Python从零到壹] 五十六.图像增强及运算篇之图像平滑(中值滤波.双边滤波)>,作者: eastmo ...
- 火山引擎 DataLeap:一家企业,数据体系要怎么搭建?
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 导读:经过十多年的发展,数据治理在传统行业以及新兴互联网公司都已经产生落地实践.字节跳动也在探索一种分布式的数据治 ...
- Freemon停止提供免费域名注册了
前言 freemon是一家国外的域名注册商,提供很多顶级的域名注册,最棒的是它还提供了五个免费的顶级一级域名注册分别有:tk.cf.ml.ga.gq,而且据我所知是不限量注册,最高一年使用期,可以免费 ...
- Spring Security 框架使用
更多内容,前往IT-BLOG 一.Spring Security 简介 Spring Security 是一个能够为基于 Spring 的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供 ...
- 为什么wait()需要在同步代码块内使用
我们还是通过源代码和代码注释来学习这个问题 我们先来看看wait方法的注释,这里截取最根源的native方法给的注释 Causes the current thread to wait until e ...
- 【LeetCode动态规划#05】背包问题的理论分析(基于代码随想录的个人理解,多图)
背包问题 问题描述 背包问题是一系列问题的统称,具体包括:01背包.完全背包.多重背包.分组背包等(仅需掌握前两种,后面的为竞赛级题目) 下面来研究01背包 实际上即使是最经典的01背包,也不会直接出 ...