包
(创建不同的文件夹,来存放程序文件),不同的包和main函数放在同一层级
Go的每一个文件都属于一个包,go是以包的形式来管理文件和项目目录结构。
不同的包里,可以有相同名字的函数
引入包,import的路径,是src后面的路径
闭包
一个函数和与其相关的引用环境组合的一个整体(实体)
闭包就是能够读取其他函数内部变量的函数。函数和它引用到的变量共同构成闭包。
var n int = 10
return func (x int ) int {
n= n+ x
return n
}
返回值是一个匿名函数,但是这个匿名函数引用到函数外的n,因此这个匿名函数就和形成了一个整体,构成闭包。
闭包练习1:
闭包可以保留上次引用的某个值
func makeSuffix(suffixstring)func (string)string {
return func(namestring)string {
if !strings.HasSuffix(name, suffix){
return name +suffix
}
return name
}
}
闭包练习2
调用闭包,传入一个文件名,如没有后缀,加后缀,如有后缀,返回文件名。
提示:strings.HasSuffix 可以判断某个字符串是否有指定后缀
func makeSuffix(suffix string) func (string) string {
return func (name string) string { //如果name没有后缀,加后缀,如有后缀,返回文件名。
if !strings.HasSuffix(name, suffix) {
return name +suffix
}
return name
}
}
func main(){
f2 :=makeSuffix(".jpg") //此处是定义f2这个函数,注意和下面给f2传入数据做对比
fmt.Println("文件名处理后", f2("winter")) //此处是给f2传入值
fmt.Println("文件名处理后", f2("bird.jpg"))
}
结果:
文件名处理后 winter.jpg
文件名处理后 bird.jpg
defer
延时机制
func sum(n1 int,n2 int) int {
//当执行到defer时,暂时不执行,会将defer后面的语句压入独立的栈(defer栈),也会把相应的值拷贝入栈(里面的值不会改变)
//当函数执行完毕后,再从栈,按照先入后出的方式出栈,执行
defer fmt.Println("ok1 n1=", n1)
defer fmt.Println("ok2 n2=", n2)
res := n1 + n2
fmt.Println("ok3 res=",res)
return res
}
func main() {
res :=sum(10, 20)
fmt.Println("res=",res)
}
结果
ok3 res= 30
ok2 n2= 20
ok1 n1= 10
res= 30
defer的价值在,当函数执行完毕后,可以及时的释放函数创建的资源
如:
func test () {
file = openfile(文件名) //关闭文件资源
defer file.close()
//接其他代码
}
func test() {
connect = openDatabase()
defer connect.close() //释放数据库资源
//接其他代码
}
在函数中经常需要创建资源,为了在函数执行完毕后及时的释放资源,所以提供defer(延时机制)
特别是拿资源(文件、数据库连接)的时候,后面添加defer file.close( )
或获取数据库的链接 ,后面添加defer connect.close( ), 进行关闭资源。
两种传递方式
1)值传递,传递的是值的拷贝,效率低,但适用于大数据
值类型:基本数据类型 int系列,float系列,bool,string,数组和结构体。
变量直接储存值,内存通常在栈中分配
2)引用传递,传递的是地址的拷贝,效率高,数据量小
引用类型:指针,slice切片,map,管道chan,interface
变量存储的是一个地址,地址对应的空间才是真正存储数据(值),内存通常在堆上分配。
一些细节
-函数字母开头大写代表公有,小写开头代表私有
-在给一个文件打包时,该包对应一个文件夹,文件夹的包名通常和文件所在的文件夹名一致,一般为小写字母
-在import包时,路径从$GOPATH的src下开始,不用带src,编译器会自动从src下开始引入
-Go支持给包取别名
-如果你要编译成一个可执行程序文件,就需要把这个包声明为main ,即package main ,这就是语法规范,
如果你写一个库,包名可以自定义
-文件的包名通常和文件所在的文件夹名一致,一般为小写字母
- 在f函数的调用机制
基本数据类型 一般在栈区,编译器存在一个逃逸分析,引用数据类型一般在堆区。
-赋值语句如 name := " abc " ,可以写在函数体内,不能写在函数体外