包概述
- 包(package)是Go语言中组织单元.包是逻辑上的分组.而物理上的分组是不同的文件夹,文件夹和包一般是对应的
- 把多个文件放入同一个文件夹中,这些文件就是在同一个包中.
- 虽然允许源码文件的package和文件夹名不同但是最终编译后都会把文件的package编译成文件夹名称.所以为防止错误最好把文件的package和文件夹名称设置成相同的
- 一个Go语言项目必须要有main包,其他自定义名称的包个数任意,根据自己的需求即可.
- Go语言在寻找包时会从GOPATH/src 路径中寻找包,如果不存在去GOROOT/src(Go语言标准库源码所在文件夹)下找
- 不同包下资源可以相互访问,在导入其他包后,可以访问包下首字母大写的内容
- 同包下不同文件中全局资源可以随意访问
自定义包
- 新建项目后在项目下新建src文件夹,在src文件夹中新建demo文件
- 在demo文件中新建demo1.go和demo2.go文件
- demo1.go文件源码如下
1
2
3
4
5
6
7
|
package demo//包为demo
import "fmt"
func demo1(){
fmt.Println("执行demo1")
}
|
1
2
3
4
5
6
7
8
|
package demo//包为demo
import "fmt"
func Demo2() {//函数名大写才能被其他包访问
fmt.Println("执行demo2")
demo1()//同包下内容任意访问
}
|
1
2
3
4
5
6
7
|
package main
import "demo"
func main() {
demo.Demo2()
}
|
- 运行整个项目后,发现可以正常调用Demo2()函数
- 整个程序目录结构如下
变量作用域
- 变量声明位置决定了变量的可访问范围(哪里能调用到变量)
- Go语言中变量的有效范围如下
- 函数级别:变量声明在函数内部,只有在函数内部才能访问,称变量为局部变量
- package 包级别,在当前包下都可以访问.称变量为全局变量.变量声明在函数外面
- 应用级别,在整个应用下任何包内都可以访问.通过首字母大小写控制
局部变量
- 局部变量一定是在函数内部
- 在哪个{}内部声明,只能在哪个{}内部访问
1
2
3
4
5
6
7
8
9
10
11
12
|
func test1() {
i := 2 //从此处开始到test1结束}任何位置都能调用i
if i>=2{
j:=3
fmt.Println(i+j)//此处可以访问i
}
fmt.Println(i)
//fmt.Println(j)//此处不能调用j,超出声明j时{}外
}
func test2() {
fmt.Println(i) //此处无法调用test1()中的i
}
|
全局变量
- 全局变量声明到函数外部,整个包都可以访问
- 如果全局变量首字母大写,跨包也可以访问.
- 声明全局变量时规范是
1
2
3
4
|
var (
变量名
变量名=值
)
|
1
2
3
4
5
6
7
8
9
10
11
12
|
var (
name = "smallming"
age = 17
)
func demo1() {
fmt.Println("名字:",name)
}
func demo2() {
fmt.Println("年龄:",age)
}
|
闭包概述
- 闭包不是Go语言独有的概念,在很多编程语言中都有闭包
- 闭包就是解决局部变量不能被外部访问一种解决方案
- 是把函数当作返回值的一种应用
代码演示
- 总体思想为:在函数内部定义局部变量,把另一个函数当作返回值,局部变量对于返回值函数就相当于全局变量,所以多次调用返回值函数局部变量的值跟随变化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package main
import "fmt"
func main() {
//res其实就是test1返回值函数,和之前匿名函数变量一个道理
res := test1()
fmt.Println(res()) //输出2
fmt.Println(res()) //输出3
fmt.Println(res()) //输出4
}
//注意此处,返回值类型是func int
func test1() func() int {
i := 1
return func() int {
i = i + 1
return i
}
}
|
- 如果重新调用test1()会重新声明及赋值局部变量i
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package main
import "fmt"
func main() {
f := test1()
fmt.Println("f的地址", f) //输出匿名函数地址
fmt.Println("f:", f()) //调用匿名函数输出2
fmt.Println("f:", f()) //调用匿名函数输出3
k := test1()
fmt.Println("k的地址", k) //输出匿名函数地址,与f相等
fmt.Println("k:", k()) //调用匿名函数输出2
fmt.Println("f:", f()) //输出:4
fmt.Println("k:", k()) //输出:3
}
func test1() func() int {
i := 1
return func() int {
i++
// 每调用一次test1()输出的地址不一样
fmt.Println("i的地址:", &i)
return i
}
}
|
golang学习一:从环境配置开始到HelloWorld入门
golang学习二:golang自带的工具
olang学习三:golang基础语法
golang学习四:流程控制
golang学习五:常用数学函数与数组
golang学习六:for循环
golang学习七:goto和label
golang学习八:切片
golang学习九:sort包、map、双向链表、双向循环链表
golang学习十:函数
golang学习十一:包的访问权限、变量作用域、闭包
golang学习十二:值传递和引用传递
golang学习十三:结构体
golang学习十四:golang中的面向对象
golang学习十五:错误异常处理
golang学习十六:文件操作
golang学习十七:反射
golang学习十八:XML操作
golang学习十九:日志
golang学习二十:golang并发编程入门
golang学习二十一:select和GC