作用域
1.go文件的包名可以理解为命名空间,包名相同则处于同一命名空间,处于一个总体作用域下
2.一对大括号开辟一个作用域
全局变量的作用域
特点:
变量的声明在包作用域下,包中任何子作用域都可用
小结:
①任意函数和文件任意位置都可以使用,
注意全局变量和函数的书写位置没有关系,例如a 函数在全局变量之前定义,但是他仍然能正常使用全局变量
因为函数的实际执行位置在全局变量定义之后
"顺序结构"
②但全局变量之间的书写位置有关联,如果全局变量A要用到全局变量B,那么B应该先于A定义
函数外要使用全局变量,必须保证全局变量已定义
举例:
package main
func a() int{
return abc
}
// 全局变量
/*
①任意函数和文件任意位置都可以使用,
注意全局变量和函数的书写位置没有关系,例如a 函数在全局变量之前定义,但是他仍然能正常使用全局变量
因为函数的实际执行位置在全局变量定义之后
*/
/*
②但全局变量之间的书写位置有关联,如果val全局变量要用到abc全局变量,那么abc应该先于val定义
函数外要使用全局变量,必须保证全局变量已定义
*/
var abc = 5
var val = abc -3
func main(){
println(bb)
}
//虽然main函数写在前面,但是真正执行时,全局变量先定义
var bb = 9
局部变量的作用域
1.特点
变量声明在大括号包裹的块作用域中,作用范围参考最近的一组大括号
2.语法
package main
import "fmt"
func main() {
/*
①
局部变量只能在定义他的函数中使用,内部代码块也属于函数自身的一部分
外部函数不能直接使用这个变量 -- 可以传参实现间接访问
实际上传参给外部函数,也相当于把外部函数暂时变成了自身的代码块
*/
err := "错误"
println(err)
/*
②
变量的作用域和代码块绑定,实际在Go中局部变量是参考代码块的
即最近的一组大括号
*/
{
localName := "local"
//localName是这个代码块中的局部变量
//在{}外无法访问
fmt.Println(localName)
//err是外面父函数的变量,相当于闭包的概念,所以可以访问
fmt.Println(err)
}
// 无法访问
// fmt.Println(localName)
/*
③ if 条件 { 代码块 }
*/
var maname string
if err == "错误" {
// 这里重新赋值了,则只能在代码块中识别
maname := "it"
fmt.Println(maname)
}
//这里的值是最初在if代码块外面定义的 maname
fmt.Println(maname)
/*
④深度理解,局部变量是相对于代码块的
*/
if err == "错误" {
abc := 2
fmt.Println(abc)
}else{
// abc在这个代码块中没有
// fmt.Println(abc)
}
/*
变量的查找逻辑 :本代码块查找 => 本代码块的祖先代码块查找 =>全局变量
按照顺序查找,最先查到的就使用,查不到就报错
*/
}
变量查找逻辑
知识点:
1.从变量使用的地方开始向上查找,
2.依次查询本作用域,祖先作用域,
3.最先查到就使用,没有查询到就报错。
举例:
package main
import "fmt"
var name = "zs"
func main() {
/*
变量的核心查找逻辑
①
查找顺序,同一代码块中往上查找,也就是按照顺序结构,从使用处往上查找
②
本代码块查找 => 本代码块的祖先代码块查找 =>全局变量
按照顺序查找,最先查到的定义位置就使用,查不到就报错
③变量的生命周期是从定义开始,他的作用域也是从定义开始
④变量的查找指的是查找变量最近定义的位置,然后计算变量的值
*/
fmt.Println(name)// zs
name := "王五"
if 5>3 {
name:="lisi"
val := name
println(val)
}
fmt.Println(name) //王五
/*
第一个打印name,按照顺序结构,从起点往上找,本代码块没有,继续祖先照,最终找到定义位置全局变量name
第二个打印name,按照顺序结构,从起点往上照,跳过子代码块,最后先找到本代码块定义位置的局部变量name
*/
}
作用域查找逻辑:
① 顺序结构,从起点往上找
② 本代码块 => 祖先代码块 => 全局变量
③ 满足①②的最近的同名变量定义位置,从这开始作用域
1036

被折叠的 条评论
为什么被折叠?



