一、第一个 Go 程序
最近在闲来无事之际开始学习点 Go 语言,Go 语言在近几年很火,有 Docker 和 Kubernetes 这两大杀器做支撑,它已经是云计算领域主流的编程语言了,并且有蚕食部分 C、C++、Java 等领域的趋势,怀着一些对新技术的兴趣,我开始学习了 Go 语言,在对其有了简单的了解之后,我渐渐开始喜欢上这门语言了。
目前我在工作中所使用的主要的编程语言是 Java,Java 虽说优秀,但是我对其并没有太大的好感,主要是它啰嗦复杂,当初学习它也主要是为了找工作。嗯。。。有一丝丝惭愧。
看到 Go 语言的 logo 我就觉得比较新奇,瞬间心情都变得不错了(Go 语言的 logo 是一只地鼠,英文称 Gopher,现在很多 Go 开发者也称自己为 Gopher 了)。
好了,闲话说了这么多,开始学习吧。
在开始之前,你需要上 Go 官网下载 Go 语言所需要的开发工具包,然后安装,安装的步骤非常简单,跟一个普通的应用程序没有差别,这里不再赘述了。
然后再选择一个自己喜欢的 IDE,我自己使用的是 Goland,当然 Vscode,Atom,Vim 也都有相应的支持 Go 语言的插件,选择适合自己的即可。
还是以一个经典的 Hello World 为例子,开始第一个 Go 语言程序:
package main import "fmt" func main() { fmt.Println("Hello World!") }
这段代码虽然简单,但是也包括了 Go 语言程序的基本结构:关键字 package
代表程序所在的模块(包),import
引入代码依赖,这两个关键字的作用和 Java 中的十分类似。关键字 func
声明一个函数,实现代码逻辑。
和其他编程语言最主要的差别是,Go 语言的启动入口 main 函数不支持任何返回值和参数,并且它必须要在名为 main 的 package 下,否则 main 只是一个普通的函数。
二、基本程序结构
2.1 变量与常量
Go 语言中的变量有下面几种声明的方式:
//1. var a int a = 1 //2. var b string = "2" //3. 短变量声明,自动类型推断 c := 10 //4. var d = 123 //5. var ( x int = 1 y string = "1" )
可以看到,Go 语言的变量声明可以使用 var 关键字,后面跟变量名称和类型,也可以不设置变量的类型,Go 会自动推断。
比较特殊的一点是 Go 可以在一行代码中对多个变量赋值(和 Python 一样),这样的话常见的交换两个变量的值就可以写得非常简洁了:
m, n := 10, 20 m, n = n, m //交换 m n 的值 Go 语言中的常量主要通过关键字 const 来实现,声明的方式一般有下面两种: const ABC = "TEST" const( A = 1 B C = "123" )
、
2.2 数据类型
Go 语言中的数据类型有下面表格中的这些:
Go 数据类型 | |
布尔值 | bool |
字符串 | string |
整数 | int int8 int16 int32 int64 |
无符号整数 | uint uint8 uint16 uint32 uint64 uintptr |
字节 | byte //uint8 的别称 |
Unicode 字符 | rune // int32 的别称 |
浮点数 | float32 float64 |
复数 | complex32 complex64 |
数据类型和主流的编程语言其实没有太大的差别,只不过需要注意下面几点:
- Go 语言中不支持隐式的类型转换,例如下面的代码是不会通过编译的:
var a int = 1 var b int64 b = a //报错 b = int64(a) //只能这样转换 • 别名和原有类型也不能进行隐式的类型转换 type MyInt int func main() { var a int = 1 var b MyInt b = a //报错 } • Go 语言中的 string 类型的默认值是空字符串而不是 nil var s string fmt.Println("*" + s + "*") //初始化 fmt.Println(len(s)) fmt.Println(s == "") //true
2.3 运算符
Go 中的运算符其实没什么可说的,如果你有其他编程语言的经验,那么可以完全忽略掉这一部分无关紧要的内容,因为它和其他主流的编程语言没有什么差别。
第一类运算符是算术运算符,有下列几种:
这里需要注意一点的是,Go 语言中不支持前置的自增和自减运算符,所以 ++A
和 --A
这种表达式是无法通过编译的。
第二类是比较运算符,这没什么可说的:
在 Go 语言中,如果是比较数组的话,那么参与比较的数组的长度必须保持一致,否则无法通过编译:
x := [...]int{1, 2, 3}
y := [...]int{1, 2, 3}
//y := [...]int{1, 2, 3, 4} 无法和 x 进行比较
fmt.Println(x == y)
第三类是逻辑运算符:
第四类是位运算符:
2.4 条件和循环
Go 语言中的条件语句仍然使用关键字 if 来实现,只不过 if 后面的条件表达式不会加上圆括号:
func oddOrEven(n int) { if n % 2 == 0{ fmt.Printf("%d is even\n", n) }else { fmt.Printf("%d is odd\n", n) } }
这里需要注意的一点是 Go 语言中的 if 条件可以支持变量赋值,如下:
if i := 1 == 1; i{ fmt.Println("i == 1") }else { fmt.Println("i != 1") }
当然这段代码仅仅是用来做演示,无任何实际的意义,if 条件中的赋值语句通常可以用来对一个函数的调用的返回值进行判断,下面是一个简单的示例(Go 语言中的函数支持多返回值,这个后面在介绍函数时会提及):
func main() { if res, err := divide(10, 0); err != nil{ fmt.Println("there is something wrong") }else { fmt.Println(res) } } func divide(x float32, y float32) (float32, error) { if y == 0{ return 0, errors.New("cant`t divide by zero") } return x / y, nil }
上面的代码在 if 条件中调用了函数,函数如果 error 类型的返回值不为空,则说明出现了错误,否则正常输出结果。
还有一个常见的条件控制语句是 switch,Go 语言中也支持,基本的用法和其他的编程语言没有太大的差别:
for i := 0; i < 5; i++ { switch i { case 1, 3: fmt.Println("odd") case 2, 4: fmt.Println("even") default: fmt.Println("not between 0-3") } }
可以看到 case 条件后面可以跟多个条件,并且每个 case 块中没有带 break 关键字,这是因为默认就有。
Go 语言中的循环只有关键字 for
来支持,而没有常见的 while
,for 关键字可以代替 while 实现其功能,如下:
//常见的for使用 for i := 0; i < 10; i++ { fmt.Println(i * i) } //当做while使用,相当于 while(x > 0) x := 10 for x > 0 { fmt.Println(x * x) x-- } //无限循环,相当于while(true) for { fmt.Println("I love Go") }