1、先在自己函数内部查找,找到后最后的结果就是内部的值
2、内部找不到,就在函数外层寻找,即查找全局变量
3、还找不到就报错:未定义
var x int = 100 //定义一个全局变量 func f1() { fmt.Println(x) } func main() { f1() }
var x int = 100 //定义一个全局变量 func f1() { fmt.Println(x) } func main() { f1() }
func f1() { var x int = 100 fmt.Println(x) }
func iff() { if y := 35; y > 19 { fmt.Println("你好") } }
func fuck() { for i := 10; i < 100; i++ { fmt.Println(i) } } fmt.Println(i) //这个也无法调用,因为i仅声明在了for循环里面
首先程序运行会进入到main函数,因为main()是入口函数,第一个需要进行执行的函数,优先级高。
在main里面定义了两个变量,正常输出num1,num2=10,20没毛病;
到了调用exchangeNum函数的时候,交换两个数的数值,再回到main函数中,按理说应该换了数值呀,为什么没有换??
func exchangeNum(num1 int, num2 int) { var t int t = num1 num1 = num2 num2 = t } func main() { num1 := 10 num2 := 20 fmt.Printf("交换前的两个数:num1=%v,num2=%v\n", num1, num2) exchangeNum(num1, num2) fmt.Printf("交换后的两个数:num1=%v,num2=%v\n", num1, num2) }
内存分析:
当我们运行Go语言时,会向内存申请一块空间,供Go语言运行起来的程序来用。
随后进行逻辑划分,就是分成三个部分。栈、堆、代码区。
基本情况下,栈是用来存放基本数据类型的,如int、string、bool等;堆是用来存放引用数据类型、复杂数据类型的;代码区就是用来存放代码。(再次强调一下,这是一般情况,特殊情况可能堆栈存放的数据会变化)
1、运行代码时,首先是入口main函数,一旦运行main函数,就会在栈里面独自创建出一块区域让函数来存放函数自身的变量等,这块区域被称作为栈帧。
func main() {
2、在main函数中执行声明变量语句,即声明num1,num2;随后在终端输出第一句话
var num1 int = 10 var num2 int = 20 fmt.Printf("交换前的两个数:num1=%v,num2=%v\n", num1, num2)
3、随后调用函数exchangeNum,内存中就会创建exchangeNum栈帧。
exchangeNum(num1, num2)
4、随后进行exchangeNum函数中的第一行语句,开始声明变量num1,num2,并从main函数中继承数值。
func exchangeNum(num1 int, num2 int) {
5、随后进入函数体,声明了t函数,开辟相应的内存空间
var t int
6、随后num1的值被传入到t,t此时被赋值
t = num1 //t = 10
7、再之后,num1的值被替换成20
num1 = num2 //num1 = 20
8、再之后,num2的值会变成10,之后结束函数运行。
num2 = t //num2 = 10 }
9、当函数运行结束后,会消除掉栈帧,即exchangeNum
函数会被销毁。所以exchangeNum
函数仅仅只是完成了自身形参的转换罢了,对main函数内部的变量没有任何影响。再之后进行打印,还是这两个数值。
/* 你有50枚金币,需要分配给以下几个人:Matthew,Sarah,Augustus,Heidi,Emilie,Peter,Giana,Adriano,Aaron,Elizabeth。 分配规则如下: a. 名字中每包含1个'e'或'E'分1枚金币 b. 名字中每包含1个'i'或'I'分2枚金币 c. 名字中每包含1个'o'或'O'分3枚金币 d: 名字中每包含1个'u'或'U'分4枚金币 写一个程序,计算每个用户分到多少金币,以及最后剩余多少金币? 程序结构如下,请实现 ‘dispatchCoin’ 函数 */ package main import "fmt" var ( coins = 50 users = []string{ "Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth", } distribution = make(map[string]int, len(users)) ) func main() { left := dispatchCoin() fmt.Println("剩下:", left) }
拿到一个题目,乍一看肯定觉着很难,慢慢分析就好了
package main import "fmt" var ( coins = 50 users = []string{ "Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth", } distribution = make(map[string]int, len(users)) ) func main() { left := dispatchCoin() fmt.Println("剩下:", left) } func dispatchCoin()(left int){ //1.依次拿到每个人的名字 //2.拿到一个人名后,根据分金币的规则去分金币 //2.1 每个人分的金币数应该保存在map中 //2.2 还要记录剩余金币数 //3. 整个第2步执行完就能得到最终每个人的金币数和剩余数 }
说到递归,应该不陌生。著名的rm -rf 就是递归删除,也就是见到一个文件夹,就会打开进去,然后遍历文件名,最后删除。
这么一想,everything这个软件,多半也是这么做的。首先是递归查询目录下的文件,随后进行删除
递归,就是在运行的过程中调用自己。
语法格式如下:
func recursion() { recursion() */\* 函数调用自身 \*/* } func main() { recursion() }
Go 语言支持递归。但我们在使用递归时,开发者需要设置退出条件,否则递归将陷入无限循环中。
递归函数对于解决数学上的问题是非常有用的,就像计算阶乘,生成斐波那契数列等。
5!=5*4*3*2*1
package main import "fmt" //递归函数 //计算n=5的阶乘 func f1(n uint64) uint64 { //return 5*4! if n <= 1 { return 1 } return n * f1(n-1) } func main() { ret := f1(5) fmt.Println(ret) }
递归函数:函数自己调用自己
递归适合处理那种问题相同\问题的规模越来越小的场景
递归一定要有一个明确的退出条件