golang基础笔记(2):程序结构
Hello World!
从每个语言学习的开始讲起:
1 | package main |
包
每个Go程序都是由包构成,每个项目都是从main
包作为入口的。
导入包
使用import
语句导入包,在Hello World
程序中,我们导入了fmt
包
1 | import "fmt" |
常常的,我们在写程序时都会遇到需要导入多个包的情况,在Golang中,我们有两种形式导入多个包:
第一种是多个import
1 | import "fmt" |
我们还可以选择将多个包用括号括起来在一个import中
1 | import ( |
值得注意的一点:import
语句只对当前文件有效
导出名
在Java中,我们用public
和private
关键词来标记一个方法是包外是否可用的。
而在Go中,使用了首字母大小写来表示这个,大写字母则代表public的。例如在我们的第一个程序中的Println就是一个以大写字母开头的。
例子
新建一个hello在目录下,并在下面新建一个Sayhello.go文件
1 | package hello |
我们将mian.go修改为
1 | package main |
我们对其运行会发现报错了,因为noHello并不是一个可以在包外调用的函数。
函数
如果你在使用一些智能的IDE,在输入func进行补全的时候,你会发现func的模板与我们学过的语言都不同的地方,它在参数列表后面,会有一个可以填入的地方
这是因为go的函数声明与其它的语言稍微有些不同
声明模板
基本函数声明模板如下
1 | func 函数名 (参数列表) (返回值列表){ |
它相较其它大多数语言,Go多了一个返回值列表
Go在函数声明上还有一个不同的点就是Go的参数是名称在前,类型在后
1 | func add(x int, y int) int { |
由于上面的例子,参数的类型是相同的,所以我们可以将其类型写在一起
1 | func add(x, y int) int { |
多值返回
Go语言支持多个返回值
1 | func swap(x, y string) (string, string) { |
命名返回值
在返回值列表中,我们可以将返回值命名。我们在给返回值赋值后,可以在最后使用一个return就可以返回所有定义的返回值。
1 | func add(x, y int) (ans int) { |
变量
声明、初始化
在前面我们提到go的函数内参数是名称在前,类型在后的,变量的声明也不例外
1 | var 变量名 类型 = 表达式 |
类型与表达式可以省略一个;
- 类型省略则会根据表达式自动推断类型
- 表达式省略则会自动初始化该变量为该类型的零值
前面我们提到Go语言支持多值返回,因此一组变量也可以通过接受函数返回值进行初始化
1 | var a, b = swap(a, b) |
在接受的时候,我们可以通过下划线抛弃我们不需要的值
1 | var a, _ = swap(a, b) |
声明也可以像import一样,用括号括起来
1 | var ( |
短声明
短声明:=
相当于是一个省略类型的声明语句,可以替代var使用
1 | 变量名 := 表达式 |
例子
1 | a, b := swap(a, b) |
符号
赋值
Go语言的赋值与大多数语言(C,Java…)的赋值都类似
相较于C、Java一类,Go语言加入了一个比较“摩登”的赋值,元祖赋值,一个例子就是上马的接受函数的多变量初始化
1 | a, b = b, a |
这使得交换两个变量的值不再需要一个中间存储值,这极大便利了变量的交换,减少了不少逻辑上思考的步骤
指针
Go语言的指针与C语言中的指针使用的方法大致相同,也都是通过*
、&
来对地址进行操作
1 | var 变量名 *类型 |
举个例子
1 | var a *int //指向整型 |
空指针
当一个指针定义后没有分配给任何变量时,他的值为nil
nil 指针也称为空指针
nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。
数据类型
基本数据类型
1 | bool |
类型转换
Go语言不提供类型自动转换
,只可以通过T(v)
的方式将值v转换为类型T
1 | var i int = 42 |
类型别名
类似于define,在编译的时候会全部替换掉
1 | type DataTYPE = string |
自定义类型
可以基于已有类型定义初新的类型,互相可以强制转换,可以添加类型自己的方法
1 | type newtype string |
逻辑控制
for
1 | for i := 0; i < 10; i++ { |
相当于是省略了小括号
注意:大括号为必须存在的
在Go语言中,是没有while
的,while可以用省略起始条件和后置语句的for替代
1 | sum := 1 |
而无限循环则为
1 | for { |
for range
for range
类似于for in
。在Go语言中,我们可以使用for range
遍历数组、切片、字符串、map及通道(channel)
1 | for key, value := range oldMap { //在数组中,key代表下标,value为对应的值 |
以上代码中,key和value都是可以省略的
如果我们想只读取一个参数,我们可以有两种形式
1 | //第一种 |
if
1 | func sqrt(x float64) string { |
Go语言允许在条件表达式之前,执行一个语句
1 | func pow(x, n, lim float64) float64 { |
这个v
的作用域是在if这个代码块内的
else与else if的用法也很简单
1 | var a int |
switch
对比 C 的 switch
,更新了以下几点:
-
case
现在不一定要是常量,也可以是表达式 -
每个分支都是默认
break
的,如果你不想跳出,可以以fallthrough
语句结束 -
支持多条件匹配
1
2
3
4switch a {
case 1,2,3,4:
default:
}
举个完整的例子
1 | package main |
defer
defer
语句会将函数推迟到外层函数返回之后执行
推迟调用的函数其参数会立即求值,但会被压入栈中,直到外层函数返回时才会按照后进先出的顺序出栈
1 | package main |