#### Go 函数,包(二)***百丈峰,松如浪,地势坤,厚德载物之像***  今天又到周五啦,你们有没有激动呢,反正我很激动,又有两天的自由了;  上一节我们学习了Go 的函数和包的一些知识 , 今天接着学习... ---##### init 函数 每个程序源文件都可以包含一个init 函数, 该函数在main 函数前执行,被Go 运行框架调用;  
package mainimport "fmt"func init(){fmt.Print("init ")
}
func main()  {fmt.Print("main")
}

  

输出结果: init main  init 函数的注意事项和细节:  1. 如果一个文件同时包含***全局变量定义,init函数和main 函数***则执行的流程为全局变量定义->init函数->main函数;  2. 其主要作用是完成一些初始化工作3. 如果多个包都有init 函数时,执行顺序为导入顺序,如:  A 导入了 B , B 导入了 C , 那么执行顺序为先执行C 中的全局变量定义,init 函数,再执行B 包中的, 最后执行A 包中的; 
package mainimport "fmt"
var a = test01()
func init(){fmt.Println("init") // 执行顺序2 fmt.Println(a) // 执行顺序3
}
func test01() int {fmt.Println("test01") // 执行顺序1return 1
}
func main()  {fmt.Println("main") // 执行顺序4
}

  

---##### 匿名函数Go 支持匿名函数,匿名函数也就是没有名字的函数,如果某一个函数希望使用一次,可以使用匿名函数,同时匿名函数也可以实现多次调用;  如果将匿名函数赋值给一个全局变量,那么这个匿名函数就成为了一个全局匿名函数,在程序的有效作用域都有效;
package mainimport "fmt"func main(){// 定义时直接调用sum := func(a,b int) int {return a +b}(10,20)fmt.Println(sum)// 将匿名函数赋值给一个变量,通过变量调用匿名函数a := func(a,b int) int {return a+b}sum = a(10,20)fmt.Println(sum)
}

  

---##### 闭包闭包实际上就是一个函数和与其相关的引用环境组合的一个整体
package mainimport "fmt"func add()func(int)int{var n int = 1return func(i int) int {n += ireturn n}
}
func main(){a := add()fmt.Println(a(1)) // 2fmt.Println(a(10)) //12fmt.Println(a(2)) //14
}

  

说明:  1. add 是一个函数,返回的数据类型是一个匿名函数;  2. 返回的匿名函数 引用到add 函数的变量n ,因此返回的匿名函数就和n 形成一个整体,构成闭包;  3. 也可以这样理解: 闭包是类,函数是方法,n 是字段,函数和它使用的n 构成闭包;  4. 因此当反复调用a 函数时, n 将累计;  
package mainimport ("fmt""strings"
)func addStr() func(str string) string {var base = "a"return func(str string) string {base += strreturn base}
}
// 判断字符串的后缀是否为指定的
func makeSuffix(suffix string) func(string) string {return func(s string) string {if !strings.HasSuffix(s,suffix) {return s + suffix}return s}
}
func main(){a := addStr()fmt.Println(a("b")) // abfmt.Println(a("c")) // abcfmt.Println(a("d")) // abcdjpg := makeSuffix(".jpg")png := makeSuffix(".png")fmt.Println(jpg("a.jpg")) // a.jpgfmt.Println(jpg("b"))  //b.jpgfmt.Println(png("a.png"))  // a.pngfmt.Println(png("b"))  //b.png
}

  

1. 返回的匿名函数和参数suffix 变量组合成一个闭包,因此传入一次可以多次调用;  ---##### defer 函数defer 也称为延时执行;  当函数执行到defer 时,暂时不执行,将defer 后的语句压入独立的栈,当函数执行完毕,return 前,再从defer 栈按照先入后出原则方式执行;  
package mainimport "fmt"func add(a,b int) int {defer fmt.Println("a=",a)  //10 输出顺序3 , 在将语句放入栈时,相关参数的值会进行拷贝defer fmt.Println("b=",b)  //20 输出顺序2 , 在将语句放入栈时,相关参数的值会进行拷贝a = 11sum := a + bdefer fmt.Println("sum=",sum) //31  输出顺序1return sum
}
func main(){sum := add(10,20)fmt.Println(sum) //31 输出顺序4
}

  

***在defer 将语句入到栈时,会将相关参数的值进行拷贝***1. 在Go 开发中通常会在创建资源(打开文件,连接数据库,锁资源)后使用defer file.Close() conn.Close()2. 在defer 后,仍可以继续使用已经创建的资源; ---##### 函数参数传递方式 上一节中已经讲过函数参数的值类型与引用类型,我们再来深入总结一下,这个知识点在编译型语言中很重要;  1. 函数参数是值类型时就是值传递,函数参数是引用类型就是引用传递; 2. 不管是值传递还是引用传递,传递给函数的都是变量的副本,不同的是值传递是值的拷贝,引用传递是地址的拷贝;  3. 一般情况下地址拷贝效率高,而值拷贝由参数的数据大小, 数据越大,效率越低; 4. 值类型: 基本数据类型int 系列, float 系列, bool, string, 数组,结构体;  5. 引用类型: 指针,slice 切片, map , chan ,interface ;   
package mainimport "fmt"// 值传递
func test01(a int){fmt.Printf("[test01] a value= %d a address=%p\n",a,&a)
}
// 对于值传递希望更改原来的值可以传入变量地址
func test03(a *int){*a = 100fmt.Printf("[test03] c value=%v c address=%p\n",*a,&a)
}
// 引用传递
func test02(a []int){fmt.Printf("[test02] b value=%v b address=%p\n",a,&a)
}
func main(){var a int = 10fmt.Printf("a value= %d a address=%p\n",a,&a)test01(a)var b = []int{1,2}fmt.Printf("b value=%v b address=%p\n",b,&b)test02(b)var c = 10test03(&c)fmt.Printf("c value=%v c address=%p\n",c,&c)
}

  

--- ##### 变量的作用域 1. 函数内部声明或定义的变量是局部变量,作用域限于函数内部;  2. 函数外部声明或定义的变量是全局变量,作用域在整个包有效,若首字母大写,则作用域为整个程序;  3. 如果变量声明或定义在代码块内,如: if/for 代码块内,则作用域仅限于代码块; 
package mainimport "fmt"// 全局变量
var name = "golang"
// 如果首字母大写,则在整个程序中有效,其它包也可以使用
var Age = 22func test01(){// 局部变量var a int = 10fmt.Println(a)// 使用全局变量fmt.Println(name)if a > 2 {// 代码块内部的局部变量, 仅限于if 代码块有效var d int = 100fmt.Println(d)}// 代码块内部的局部变量, 仅限于if 代码块有效//fmt.Println(d) // error
}
func main(){// 局部变量var b int = 1fmt.Println(b)// 使用全局变量fmt.Println(name)test01()
}

  个人微信公众号上有最新文章: 欢迎大家关注一同学习交流

转载于:https://www.cnblogs.com/Mail-maomao/p/11411767.html

Go 函数,包(二)相关推荐

  1. Python的数据科学函数包(二)——pandas(series dataframe)(loc iloc ix)(csv文件)

    pandas 1.pandas数据的存储相对来说比较简单,它就只有两种非常重要的数据类型,一种叫series,一种叫dataframe series是指那些一维的数据,dataframe是指那些二维的 ...

  2. R语言使用yardstick包的pr_curve函数评估二分类(binary)模型的性能、并使用autoplot函数可视化模型的PR曲线(precision recall)

    R语言使用yardstick包的pr_curve函数评估二分类(binary)模型的性能.并使用autoplot函数可视化模型的PR曲线(precision recall) 目录

  3. R语言使用compareGroups包compareGroups函数生成表统计表、createTable函数创建二元表、并导出结果到文档(doc、csv、xlsx、pdf)

    R语言使用compareGroups包compareGroups函数生成表统计表.createTable函数创建二元表.并导出结果到文档(doc.csv.xlsx.pdf) 目录 R语言使用compa ...

  4. python语言基础实验_实验二Python语言基础函数包练习.doc

    实验二Python语言基础函数包练习 实验 Python语言基础函数包练习:1208 学号: 实验目的 1.Python语言包,如math.NumPySciPy和Matplotlib等函数包的使用实验 ...

  5. R语言使用epiDisplay包的logistic.display函数获取二分类logistic回归模型的汇总统计信息(自变量初始和调整后的优势比及置信区间,回归系数的Wald检验的p值、简化汇总结果

    R语言使用epiDisplay包的logistic.display函数获取二分类logistic回归模型的汇总统计信息(自变量初始和调整后的优势比及置信区间,回归系数的Wald检验的p值.自变量的似然 ...

  6. R语言glm函数构建二分类logistic回归模型、epiDisplay包logistic.display函数获取模型汇总统计信息(自变量初始和调整后的优势比及置信区间,回归系数的Wald检验的p值

    R语言glm函数构建二分类logistic回归模型(family参数为binomial).使用epiDisplay包logistic.display函数获取模型汇总统计信息(自变量初始和调整后的优势比 ...

  7. python函数包_python-函数包和模块

    python函数的作用: 在Python代码段中如果有一段几十行的代码,需要多次重复使用这几十行代码时,为了提高代码的可用性,将代码段放进函数体内,以后在使用中直接调用该函数模块即可,函数是一个独立的 ...

  8. R语言实现SOM(自组织映射)模型(三个函数包+代码)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- SOM自组织映射神经网络模型 的R语言实现 笔 ...

  9. 黑马程序员——c语言学习心得——函数传递二维数组

    黑马程序员--c语言学习心得--函数传递二维数组 -------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.定义指针的时候一定要初始化.    变量 ...

最新文章

  1. (翻译) MongoDB(7) 安装MongoDB
  2. MIRO报错Table T169V: entry 1110 does not exist
  3. linux——yum的搭建说明
  4. Python之在函数中使用列表作为默认参数
  5. 收藏 | 损失函数理解汇总,结合PyTorch1.7和TensorFlow2
  6. 计算机有没有开启ntp服务器,让你的Windows电脑成为一台NTP校时服务器
  7. Android中后台线程如何与UI线程交互
  8. 数字图像处理与python实现 pdf_python数字图像处理实现直方图与均衡化
  9. 金山PDF转WOED 1.3.0.1007版本
  10. sql 脚本 昨天的日期获取,今天的前一天的数据获取, 前两个月的今天
  11. Python单词识别
  12. MDCC 2016参会总结
  13. 深度学习模型知识产权保护怎么做?看看IJCAI 2021这场Workshop说了什么
  14. chrome是什么?
  15. 一文看懂5种ESD防护方法!
  16. Cypress 元素定位
  17. JavaScript高级编程设计(第三版)——第四章:变量作用域和内存问题
  18. 「 机器人学 」“姿态角 roll、yaw、pitch”讲解
  19. 【打卡】21天学习挑战赛—RK3399平台开发入门到精通-day9
  20. 对角阵在matlab,MATLABSimulink实现对角阵解耦(模型和代码).pdf

热门文章

  1. 字节面试现场,问我如何高效设计一个LRU
  2. codeforces 521div3(D Cutting Out)java
  3. java.util.Map中put,computeIfAbsent与putIfAbsent区别
  4. keras cnn注意力机制_从发展历史视角解析Transformer:从全连接CNN到Transformer
  5. python里的关键字有哪些_Python中的yield关键字做了什么?
  6. linux命令的导入,[导入]Linux基本命令
  7. 这是阿里技术专家对 SRE 和稳定性保障的理解
  8. latex字体_[LaTeX 引擎] XeLaTeX + macOS,通过字体名调用发行版字体
  9. mysql字符串函数混合使用_MySql字符串函数使用技巧
  10. 1、spring的IOC