Go程序开发注意事项
- Go 源文件以 “go” 为扩展名。
- Go 应用程序的执行入口是 main()函数。 这个是和其它编程语言(比如 java/c)
- Go 语言严格区分大小写。
- Go 方法由一条条语句构成,每个语句后不需要分号(Go 语言会在每行后自动加分号),这也体现出 Golang 的简洁性。
- Go 编译器是一行行进行编译的,因此我们一行就写一条语句,不能把多条语句写在同一个,否
则报错 - go 语言定义的变量或者 import 的包如果没有使用到,代码不能编译通过。
- 大括号都是成对出现的,缺一不可。
- main函数必须在main包里面
- 赋值!=初始化,
:=为声明加赋值即var name type \n name = xxx,所以不能用于全局变量初始化,因为赋值语句是执行语句,只能出现在函数体内,要想声明全局变量和初始化,需要用var name type = xxx or var name = xxx
if注意事项
- 尽管if后面只有一条语句,也需要用{}包裹
- if的条件判断语句中允许声明一个变量,作用域只在该条件逻辑块内
- if后面的小括号官方不推荐写,但如果去掉括号影响语义的条件表达式,则不能去
- 双分支中,else的位置:else不能换行
if xxx {
} else {
}
- if后面的条件必须是条件表达式,不能是赋值语句
switch case
- switch中匹配项后面不需要加break
- case后面可以跟多个表达式,使用逗号隔开
- switch后面的数据类型和case后面的数据类型必须一致,否则报错,一个具体的值是可以的,因为字面量不包含数据类型
- case后面的值若是常量值(字面量),则要求不能重复
- default不是必须的
- switch后也可以不带表达式,类似if-else分支来使用,而且在case中,也可以对范围进行判断
- switch后面也可以直接声明/定义一个变量,以分号结束,不推荐
- switch穿透(fallthrough):在case语句后面加fallthrough,则会继续执行下一个case(不会判断下一个case是否符合,而且默认穿透一层)
- Type Switch:switch语句还可以被用于type-switch来判断某个interface变量中实际指向的变量类型
for
- 特殊的for用法(和其他语言的while用法一致)
j := true
for j {
fmt.Println("小日本")
fmt.Scanln(&j)
}
-
for {} <==> for ; ; {}
-
包
- go的每一个文件都是属于一个包的,也就是说go是以包的形式来管理文件和项目目录结构的
- 在import包时,路径从$GOPATH的src下开始,编译器会自动从src下开始引入
- 在引入包时,支持给包取别名,这样在后面调用时可以用别名调用,原先的包名不可调用
函数
-
go不支持传统的函数重载
-
在go中,函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量了,通过该变量可以对函数调用
-
函数既然是数据类型,便可以作为形参,并且调用
-
为了简化数据类型定义,go支持自定义数据类型(起别名)
type myInt int
注意:myInt和int虽然都是int类型,但是go认为这两个是两个不同的类型也就是说myInt类型的变量不能直接赋值给int类型的变量,如果要赋值需要强转
-
go支持对返回值命名(下面代码就不需要重复定义,并且返回值会自动识别)
func method(num1 int, num2 int) (sum int, sub int) { sum = num1 + num2 sub = num1 - num2 return }
-
使用_可以忽略返回值
-
go支持可变参数,如果用可变参数,必须放在形参列表的最后一个
init
-
如果一个文件同时包含全局变量定义,init函数和main函数,则执行流程为变量定义->init函数->main函数,另外其他程序在引包的时候,就会调用其init函数
执行顺序:被引入文件的全局变量声明->被引入文件的init()->本文件的全局变量声明->本文件的init()->本文件main()
匿名函数(达成在函数中定义函数完成特殊需求)
- 声明时调用
- 赋值给一个变量(可以是局部变量也可以是全局变量),通过变量调用
defer
- 遇到defer语句时,暂时不会执行defer后的语句,而是将其压入一个独立的栈,最后执行
- 在将defer语句放入栈中时,也会将相关的值拷贝入栈
- 通常做法是,创建一个资源后立即defer,defer后仍可以使用创建的资源,函数完毕后系统会依次从defer栈中取出语句关闭资源
数组
- 数组在golang中是值类型,不是引用类型,所以打印出来是数组内的值,而在java中打印的就是地址
- 在数组中,数组的长度是类型的一部分,所以[3]int 和 [4]int 是两种不同是数据类型,[]int 是切片类型
切片
- 切片的底层数据结构本质是一个结构体,有三部分:<1>引用内容的首地址<2>length<3>capacity
- *使用:*定义一个切片,然后让切片引用一个已经创建好的数组(通过切片和数组都能访问到里面的元素)、通过make来创建切片、
- 通过make创建的切片对应的数组是make底层维护的,对外不可见,即只能用slice来访问
- 切片可以继续切片
- copy()只看len不看cap,如果source的len>target的len,则能够拷贝几个就拷贝几个,不会报错,和cap无关,也就是说哪怕target的cap大于source的len,也是看len来拷贝