目录
前言
由于工作变动,我现在已经开始使用Golang了。用了一段时间之后,我发现Golang(后面简称Go)中的语法糖还蛮多的,有些语法糖还让会让人很懵逼。那么接下来,让我以一个曾经的 Java CURD boy,来说一说 Go 中的语法糖。
进入正题
至于什么是语法糖,名词解释我就不解释了,老司机自然是懂,新手司机想了解的可以去百度问一下。闲话少说我们直接开讲。
可变长参数
...
切片
func test(a int, b ...int) { fmt.Println("a=", a, ",b=", b, ",b的类型=", reflect.TypeOf(b)) return }
输出结果如下:
a= 1 ,b= [] ,b的类型= []int
为啥说可变长参数的值用切片来解析,而不是数组。为什么是这样有兴趣的朋友可以思考一下
可变长参数这个语法糖,不是Go独有的,Java中也有,不同的是Java是通过数组实现此语法糖的。从实际开发经验来看,这个语法糖我在使用Java开发时,貌似一次都没有用过,用Go开发的时候我用的次数还挺多的,具体在什么地方用,后面有机会我再说说它是如何使用的。
声明不定长数组
...
// Go的实现:数组长度是4,等同于 a := [4]{1, 2, 3, 4} a := [...]int{1, 2, 3, 4}
这个Java中有实现,而且感觉比Go的还简单,具体如下:
// Java的实现:数组长度是4 int[] x = {1,2,3,4};
在我短暂的职业生涯中,无论我使用Java还是Go开发的时候,数组使用的频率都是比较少的。
...
... 操作符
...
func funcName(nums ...int)params = []int{1,2,3}func ThreeParamFunc(a, b, c int)ThreeParamFunc(params...)...
// 数组 var number = [1,2,3,4,5,6] console.log(...number) //1 2 3 4 5 6 //对象 var man = {name:'蔡',height:180} console.log({...man}) / {name:'蔡',height:180}
...
arr := [...]int{1,2,3} $ go test ./...
切片循环
for range
只遍历不关心数据,适用于切片、数组、字符串、map、channel
for range T {}
遍历获取索引或数组,切片,数组、字符串就是索引,map就是key,channel就是数据
for key := range T{}
遍历获取索引和数据,适用于切片、数组、字符串,第一个参数就是索引,第二个参数就是对应的元素值,map 第一个参数就是key,第二个参数就是对应的值;
for key, value := range T{}
_
for _, value := range T{}
keySet()values()
// 打印键集合 for (String key : map.keySet()) { System.out.println(key); } // 打印值集合 for (String value : map.values()) { System.out.println(value); }
另外注意一点,在Go中如果一个切片是nil的时候,我们对他进行遍历或者append操作的时候,是不会出现报错的,这一点很不错,省的像用Java时遍历对象需要判断他是否为null。
func main() { temp := make([]int, 0) temp = nil for _, val := range temp { fmt.Println("val=", val) } temp = append(temp, 1) fmt.Println("val=", temp) }
上述操作都是不会报错的,大家放心食用!
忽略变量、字段或者导包
_
-
type Item struct{ Id uint32 `json:"id"` Name string `json: "name"` Password string `json: "-"` }
transient
json.Marshalomitempty
type Item struct{ Id uint32 `json:"id"` Name string `json: "name,omitempty"` Password string `json: "-"` }
这里说一下,在Java里类型分为基本类型和包装类型,Java类初始化的时候属性为基本类型如果没有赋予初始值,默认值是0。包装类型声明时没有赋值的话的初始值为null。Go中初始化时没有赋值的变量的默认值如下:
- 布尔类型的默认为false
- 数值类型的默认为0
- 字符串类型的默认为空字符串""
- 指针类型、函数、接口、切片、通道和map默认值为nil
这样看来Java和Go这个场景下处理方式,有相似和不同之处,大家开发的时候要注意,由Java转Go的同学开发时,千万别搞混了。
短变量声明
在强类型语言中,声明一个变量都需要指定变量的类型。可能语言的开发者觉得这样做对开发者不太友好,就搞了个变量声明不用指定类型的语法糖,其实这个玩意说起来就是类型推导(Java8之后的版本貌似已经有了),开发者只管定义变量,类型由语言编译器来处理。
a := 10 #等用于 var a int = 10 #或者是 b:=fucName()
b:=fucName()bb
我之前写过几年的PHP,后来转了Java,再到现在写Go。我发现各种开发语言都在进步,而且还相互模仿,PHP中函数之前不用指定形参类型,PHP8中好像可以指定形参类型了。总之就是强弱类型的语言在相互靠拢。
另类的返回值
在Go语言中,允许您使用return语句从一个函数返回多个值。换句话说,在函数中,单个return语句可以返回多个值。返回值的类型类似于参数列表中定义的参数的类型。
func func1(a string, b int) int { fmt.Println("func1------------") fmt.Println("a1 = ", a) fmt.Println("b1 = ", b) c := 100 return c }
可以这样写:返回多个返回值,形参命名
func func2(a string, b int) (int, int) { fmt.Println("func2------------") fmt.Println("a2 = ", a) fmt.Println("b2 = ", b) return 12, 33 }
可以这样写:返回多个返回值,形参匿名
func func3(a string, b int) (int, int) { fmt.Println("func3------------") fmt.Println("a2 = ", a) fmt.Println("b2 = ", b) return 12, 33 }
Open
func Open(dialector Dialector, opts ...Option) (db *DB, err error) { config := &Config{} if d, ok := dialector.(interface{ Apply(*Config) error }); ok { if err = d.Apply(config); err != nil { return } } # 省略此处无用代码 db = &DB{Config: config, clone: 1} db.callbacks = initializeCallbacks(db) # 省略此处无用代码 preparedStmt := &PreparedStmtDB{ ConnPool: db.ConnPool, Stmts: map[string]Stmt{}, Mux: &sync.RWMutex{}, PreparedSQL: make([]string, 0, 100), } db.cacheStore.Store(preparedStmtDBKey, preparedStmt) # 省略此处无用代码 db.Statement = &Statement{ DB: db, ConnPool: db.ConnPool, Context: context.Background(), Clauses: map[string]clause.Clause{}, } # 省略此处无用代码 return }
returndberror
func func4(a string, b int) (r1 int, r2 int) { fmt.Println("func4------------") //r1 r2输入fool3的形参,初始化默认的值是0 //r1 r2 作用域空间是 func4 整个函数体的{}空间 fmt.Println("r1 = ", r1) fmt.Println("r2 = ", r2) r1 = b * 2 r2 = 2000 return }
r1r2
总结
本文介绍了一些Go语言中的语法糖,当然并不全面,应该还有其他的没有介绍,希望大家能够看完本篇文章后,能了解并掌握,并能在实际开发中运用到,当然其中的函数多返回值的懵逼写法,就由大家自行判断是用还是不用了。