- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
语法糖(Syntactic sugar)的概念是由英国计算机科学家彼得·兰丁提出的,用于表示编程语言中的某种类型的语法,这些语法不会影响功能,但使用起来却很方便。 语法糖,也称糖语法,这些语法不仅不会影响功能, 编译后的结果跟不使用语法糖也一样。 语法糖,有可能让代码编写变得简单,也有可能让代码可读性更高,但有时也会给你一个意外让您的代码出问题。Golang中的语法糖语法有很多,本文将讲解Golang中常用的语法糖.
规则:简短变量声明符这个语法糖使用起来很方便,导致你可能随手就会使用它定义一个变量,往往程序的bug就是随手写出来的,在这里说一下简短变量声明的原理和规则.
使用 := 一次可以声明多个变量,例如:
i, j := 0, 0 j, k := 1, 1
调用可变参函数时,可变参部分是可以不传值的,例如:
func ExampleGreetingWithoutParameter() { sugar.Greeting("nobody") // OutPut: // Nobody to say hi. }
这里没有传递第二个参数。可变参数不传递的话,默认为nil.
调用可变参函数时,可变参数部分可以传递多个值,例如:
func ExampleGreetingWithParameter() { sugar.Greeting("hello:", "Joe", "Anna", "Eileen") // OutPut: // hello: Joe // hello: Anna // hello: Eileen }
可变参数可以有多个。多个参数将会生成一个切片传入,函数内部按照切片来处理.
调用可变参函数时,可变参数部分可以直接传递一个切片。参数部分需要使用 slice... 来表示切片。例如:
func ExampleGreetingWithSlice() { guest := []string{"Joe", "Anna", "Eileen"} sugar.Greeting("hello:", guest...) // OutPut: // hello: Joe // hello: Anna // hello: Eileen }
此时需要注意的一点是,切片传入时不会生成新的切片,也就是说函数内部使用的切片与传入的切片共享相同的存储空间。说得再直白一点就是,如果函数内部修改了切片,可能会影响外部调用的函数.
在 Go 语言中,new 函数用于动态地分配内存,返回一个 指向新分配的零值的指针 。它的语法如下:
func new(Type) *Type
其中,Type 表示要分配的内存的类型,new 函数返回一个指向 Type 类型的新分配的零值的指针。但是需要注意的是, new 函数只分配内存,并返回指向新分配的零值的指针,而不会初始化该内存.
所谓零值,是指 Go 语言中变量在声明时自动赋予的默认值。对于基本类型来说,它们的零值如下:
因此,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"。接下来,使用结构体字面量或者显式为其赋值,将其初始化为非零值。 。
注意 1:p3 := new(Person) 返回是指向新分配的Person类型对象零值的指针,按照我们对指针语法的了解,基于p3显示赋值的话需要使用如下语法进行赋值:
(*p3).name = "Jerry" (*p3).age = 20 (*p3).sex = 0而我们在对指针类型结构体对象赋值的时候一般都很少会带着*,这也是Go指针语法糖为我们做的简化,这部分在后文会详细介绍。 。
注意 2:new函数更多细节介绍,请参见《 Go语言new( )函数 》这篇博文.
很明显,new函数的设计同样是为了方便程序员的使用。 。
我么都知道数组长度是固定的,所以在声明数组的时候都要指定长度,Go里提供了一种偷懒的声明方式,即使用 ... 操作符声明数组时,我们只管填充元素值,其他的由Go编译器来处理.
// Go的实现:数组长度是4,等同于 a := [4]{1, 2, 3, 4} a := [...]int{1, 2, 3, 4}
有时我们想声明一个大数组,但是某些index想设置特别的值也可以使用...操作符搞定: 。
a := [...]int{1: 20, 999: 10} // 数组长度是100, 下标1的元素值是20,下标999的元素值是10,其他元素值都是0
Go语言提供了先于main函数执行的init函数,初始化每个包后会自动执行init函数,每个包中可以有多个init函数,每个包中的源文件中也可以有多个init函数,加载顺序如下:
从当前包开始,如果当前包包含多个依赖包,则先初始化依赖包,层层递归初始化各个包,在每一个包中,按照源文件的字典序从前往后执行,每一个源文件中,优先初始化常量、变量,最后初始化init函数,当出现多个init函数时,则按照顺序从前往后依次执行,每一个包完成加载后,递归返回,最后在初始化当前包! 。
init函数实现了sync.Once,无论包被导入多少次,init函数只会被执行一次,所以使用init可以应用在服务注册、中间件初始化、实现单例模式等等,比如我们经常使用的pprof工具(Go性能分析工具),它就使用到了init函数,在init函数里面进行路由注册:
//go/1.15.7/libexec/src/cmd/trace/pprof.go func init() { http.HandleFunc("/io", serveSVGProfile(pprofByGoroutine(computePprofIO))) http.HandleFunc("/block", serveSVGProfile(pprofByGoroutine(computePprofBlock))) http.HandleFunc("/syscall", serveSVGProfile(pprofByGoroutine(computePprofSyscall))) http.HandleFunc("/sched", serveSVGProfile(pprofByGoroutine(computePprofSched))) http.HandleFunc("/regionio", serveSVGProfile(pprofByRegion(computePprofIO))) http.HandleFunc("/regionblock", serveSVGProfile(pprofByRegion(computePprofBlock))) http.HandleFunc("/regionsyscall", serveSVGProfile(pprofByRegion(computePprofSyscall))) http.HandleFunc("/regionsched", serveSVGProfile(pprofByRegion(computePprofSched))) }
注意 1:Go中main函数和init函数的调用链关系图可以参见《 (转)Go中的main函数和init函数 》这篇博文.
Go语言在设计师有代码洁癖,在设计上尽可能避免代码滥用,所以Go语言的导包必须要使用,如果导包了但是没有使用的话就会产生编译错误,但有些场景我们会遇到只想导包,但是不使用的情况,比如上文提到的init函数,我们只想初始化包里的init函数,但是不会使用包内的任何方法,这时就可以使用 _ 操作符号重命名导入一个不使用的包:
import _ "net/http/pprof" import _ "github.com/go-sql-driver/mysql"
注意 1:忽略导包的详细使用可以参见《 Golang中下划线的使用 》这篇博文.
这个应该是最简单的用途,比如某个函数返回三个参数,但是我们只需要其中的两个,另外一个参数可以忽略,这样的话代码可以这样写:
v1, v2, _ := function(...)
最后此篇关于Golang常用语法糖的文章就讲到这里了,如果你想了解更多关于Golang常用语法糖的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在此处回答的另一个问题中,我发现了以下 JavaScript代码: function _dom_trackActiveElement(evt) { if (evt && evt.target)
if (A == 0) OR (B == 0) 怎么说? 最佳答案 只是为了讽刺: if (A === 0 || B === 0) 关于语法,我们在Stack Overflow上找到一个类似的问题:
var ret = [] ,xresult = document.evaluate(exp, rootEl, null, X
我一直在寻找一些类似于下例的 JavaScript。有人可以解释一下吗,因为我以前从未见过这样编写的 JavaScript。 “SomethingHere”和冒号代表什么?我习惯于看到函数 myFun
这是我的程序: delimiter // drop procedure if exists migContactToActor; create procedure migContactToActor(
我遇到了一个问题。我一直在使用 gcc 编译/汇编我的 C 代码一段时间,并且习惯了阅读 Intel 汇编语法。我在生成程序集文件时使用了 -masm=intel 标志。 但是最近因为公司迁移,拿到了
自上而下和自下而上语法有什么区别?举个例子就太好了。 最佳答案 首先,语法本身不是自上而下或自下而上的,解析器是(尽管有些语法可以被其中一个解析,但不能被另一个解析)。 从实践的角度来看,主要区别在于
我知道这是草率的代码,但它是: display dialog ("Start Screensaver. Please type: matrix, coffee, waffles, star, wate
这个问题已经有答案了: Giving name to a loop (6 个回答) 已关闭 8 年前。 我见过这个字符在 C# 中使用,就像 Java 中的扩展一样,但最近我在代码中发现了这个 loo
我正在尝试编写一个函数来检查字符串是否为回文,但我认为在使用字符串指针时存在一些错误。这段代码有什么问题? #include #include #define MAX 1000 int IsPalin
所以在this question我询问了一些 Javascript 是如何被压缩的。问题已得到解答,但以下片段让我非常困惑,以至于我不得不问另一个问题。在这里: for (Y = 0; $ = 'zx
假设我有一个接受这些参数的函数。 int create(Ptr * p,void * (*insert)(void *, void *)) { //return something later } 结
这个问题已经有答案了: Bitwise '&' operator (6 个回答) 已关闭 5 年前。 我在代码中找到了这个,但我从未遇到过像 & 这样的事情,仅 && if ((code & 1) =
我在处理继承类及其中的构造函数和方法的语法时遇到了问题。 我想实现一个类日期和一个子类 date_ISO,它们将按特定顺序设置给定的日、月、年,并通过一种方法将其写入字符串。我觉得我的基类日期工作正常
我正在尝试通过存储过程填充表,如下所示: SET @resultsCount = (SELECT COUNT(*) FROM tableA); SET @i = 0; WHILE @i THEN
谁能解释一下下面代码中的“<<”? mysql test<
刚刚开始学习 MySQL,这是一个菜鸟问题,也是我在 StackOverflow 上的第一个问题。 假设我有 12 个订单状态,我想从其中的 5 个中选择总计。我会使用: SELECT SUM(tot
我的编程背景是在学校学过一点Java。由于某些原因,JavaScript 语法往往让我感到困惑。下面的 JavaScript 代码是一种我不知道如何构成的语法模式: foo.ready = funct
我正在阅读 javascript 源代码,并且我以前没有编写过 javascript。我对它的一些语法感到困惑。 $(function () { window.onload=function
我什至不知道如何命名我想要的东西。那么让我举个例子来解释一下。 虽然火狐使用textContent,但其他浏览器支持innerText属性。顺便说一句,如果我使用了错误的术语,请纠正我。无论如何,到目
我是一名优秀的程序员,十分优秀!