这是我参与「第五届青训营 」伴学笔记创作活动的第2天。
Go语言的标识符
概念
1.golang对各种变量、方法、函数等命名时使用的字符序列称为标识符
2.凡是自己可以起名字的地方都叫标识符
命令规则
1.由26个英文字母大小写,0-9数字,_组成
2.数字不可以开头
3.golang中严格区分大小写
4.标识符不能包含空格
5.下划线在go中是一个特殊的标识符,称为空标识符,可以代表任何其他的标识符,但是它对应的值会被忽略
(例如:忽略某个返回值),所以仅能作为占位符,不能作为标识符
6.不能以系统关键字作为标识符,break等
7.go中有一个预声明的标识符nil,表示指针、通道、函数、接口、映射或切片类型等的空值,可以被赋值
注意事项
1.包名:保持package的名字和目录保持一致,不要和标准库命名冲突
2.采用驼峰式写法
3.如果变量名、函数名、常量名首字母大写,则可以被其他的包访问,如果首字母小写,
则只能在本包中使用,即首字母大写是公开(public)的,首字母小写是私有(private)的,这一点可以和java类比
Go较为独特的循环语句、跳转控制语句
三种for循环
go语言有一点是较为特殊的,它没有while循环,取而代之的是多种的for循环语句。
第一种for循环,和java、c++类似:
for i := 1; i <= 10; i++{
fmt.Println("hello", i)
}
第二种for循环,类似while:
j := 1
for j <= 10{
fmt.Println("hello", j)
j++
}
第三种for循环,类似do while:
k := 1
for{
if k <= 10{
fmt.Println("ok~")
} else {
break
}
跳转控制中的goto
go中有类似汇编语言的goto语法,可以直接跳转到程序的某一行,实际上这种语法java中也有,但和java一样,由于这种语法常造成程序的混乱,并不常用,但如果你之前只比较熟悉Python,这一部分还是有一定阅读的价值的。
对于goto:
1.go语言的goto语句可以无条件地转移到程序中指定的行
2.goto语句通常与条件语句配合使用,可以实现条件转移,跳出循环体等功能
3.在go程序设计中一般不主张使用goto语句,以免造成程序流程的混乱,使理解和调试程序都产生困难
基本语法:
goto label
...
label:statement
例如:
var n int = 50
print("hell1")
if n > 20 {
goto label1
}
print("hell2") // 不执行了
print("hell3") // 不执行了
print("hell4") // 不执行了
label1:
print("hell5")
print("hell6")
函数与包
函数
基本语法
func 函数名 (形参列表) (返回值列表){
执行语句
return 返回值列表
}
注意事项
1.形参列表和返回值列表的数据类型可以是值类型,也可以是引用类型
2.基本数据类型和数组默认都是值传递的,即进行值拷贝。在函数内修改,不会影响到原来的值
3.首字母大写为public,可以被其他包使用,如果小写为private,不能被其他包使用
4.如果希望函数内的变量能修改函数外的变量(默认是以值类型传递的),可以传入变量的地址&,函数内以指针的方式操作变量
5.go函数不支持重载
6.在go中,函数也是一种数据类型,可以赋给一个变量,则该变量就是一个函数类型的变量了,通过该变量可以对函数调用
比如这样:
func myFun(funvar func(int, int) int, num1 int, num2 int) int {
return funvar(num1, num2)
}
res2 := myFun(getSum, 20, 70)
fmt.Println(res2)
7.go支持自定义数据类型
基本语法:
type 自定义数据类型名 数据类型 相当于一个别名
如:type mySum func(int, int)int
8.支持对函数返回值命名
func cal(n1 int, n2 int) (sum int, sub int) {
sum = n1 + n2
sub = n1 - n2
return //此时就不用再声明要返回的值了
}
此时编译器在运行该函数时,会开始就根据指定的类型创建返回值,初始默认为0
8.使用_标识符,忽略返回值
9.go支持可变参数
func sum(n1 int, args... int) int {
}
args是slice切片,通过args[index]可以访问到各个值
函数参数的传递方式
值类型和引用类型
值类型包括:基本数据类型 int系列、float系列、bool、string、数组、结构体struct
引用类型:指针、slice切片、map、管道chan、interface等
值类型:变量直接存储值,内存通常在栈中分配
引用类型:变量存储的是一个地址,这个地址指向的空间才是真正存储的数据(值),内存通常在堆上分配,当没有任何变量引用这个地址时,该地址对应的数据空间就成为一个垃圾,由GC来回收
两种传递方式:
1.值传递
2.引用传递
传递的都是变量的副本,值传递拷贝值,引用传递拷贝地址,一般来说,地址拷贝效率高,因为数据量小
包
包的本质实际上就是创建不同的文件夹,来存放程序文件
作用:
1.区分相同名字的函数、变量等标识符
2.当程序文件很多时,可以很好的管理项目
3.控制函数、变量等访问范围,即作用域
package指令在文件第一行,然后是import指令
基本语法:
打包:package 包名(不需要和文件夹名保持一致)
引入包:import "包的路径"
路径从$GOPATH 下的src下开始,不用带src,编译器会自动从src包下开始引入
import{
"fmt"
utils "go_code/base_part/for_cyclic/utils"
}
如果要编译成一个可执行文件,需要将这个包声明为main,即package.main 这是一个语法规范,如果写的是一个库,包名可以自定义
特殊函数与闭包
init函数
每一个源文件都可以包含一个init函数,该函数会在main函数执行前被Go运行框架调用,就像__init__之于Python中的类一样。
注意事项
1.如果一个文件同时包含全局变量定义、init函数和main函数,则执行流程是变量定义 -> init函数 -> main函数
2.init主要作用是完成初始化工作
3.被引入文件的变量定义、init函数的执行顺序先于主文件
匿名函数
如果某个函数只是希望使用一次,就可以考虑使用匿名函数,匿名函数也可以多次调用。
使用方式1: 在定义匿名函数时就直接调用
res := func(n1 int, n2 int) int {
return n1 + n2
}(10, 20)
使用方式2:
将匿名函数赋给一个变量(函数变量),再通过该变量来调用匿名函数
a := func(n1 int, n2 int) int {
return n1 - n2
}
res2 := a(10, 4)
fmt.Println(res2)
全局匿名函数:
将匿名函数赋给一个全局变量,则成为一个全局匿名函数,可以在程序中有效
// 全局匿名函数
var (
Fun1 = func(n1 int, n2 int) int {
return n1 * n2
}
)
res3 := Fun1(4, 7)
fmt.Println(res3) // 这两行在main函数中
闭包
闭包就是一个函数与其相关的引用环境组成的一个整体
以一个累加器为例:
func AddUpper() func(int) int {
var n int = 10
var str = "hello"
return func(x int) int {
n += x
str += "a"
fmt.Println(str)
return n
}
}
返回的数据类型是func (int) int
闭包返回的是一个函数,但是该函数引用到了函数外的n,因此这个函数与n形成了一个整体,构成闭包
可以理解为闭包是一个类、函数是操作,n是字段
n只会初始化一次,在调用过一次后,n的值就会永远改变了
闭包 = 函数 + 变量 函数的返回结果影响变量的值
小应用(伪代码)
文件后缀自动补全
func makeSuffix(suffix string) func(string) string{
return func (name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
匿名函数和suffix变量成为了一个闭包
Go的defer机制
在函数中,常常需要创建资源,比如数据库连接、文件句柄、锁等,为了在函数执行完毕后,及时的释放资源,go的设计提供了defer(延时机制)
加上defer,函数在执行完毕之后,指定的资源会被关闭
1.当代码执行到defer时,会先不执行其后的内容,而先让编译器将defer后的内容压入到独立的栈(可理解为一个defer栈)中,再执行之后的语句
2.当函数执行完毕后,再从defer栈,从栈顶按先入后出的方式出栈执行
3.在defer语句放入到栈时,会将相关的值拷贝同时入栈
主要用途(伪代码):
关闭文件 defer file.close()
释放数据库资源 defer connect.close()
优点:这是一种简洁的机制,使得开发者不必关心要在什么时候关闭资源
以上内容若有不正之处,恳请您不吝指正!