• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

Go语言学习笔记(八)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

函数进阶

函数作用域

1.全局变量,在程序整个生命周期都是有效的
2.局部变量:函数内定义/语句块内定义

变量可变性

包内任何变量或者函数都是能访问的。包外的话,首字母大写是可导出的能够被其他包访问或调用。小写表示是私有的,不能被外部的包访问。同一个包内大小写的全局变量或者函数是能被直接调用的。

跨包导入和调用:
  1: 导入:
  2: import (
  3: 	github.com\apple_school\listen1\function\calc"
  4: )
  5: 调用:
  6: calc.Add()
  7: calc.A
匿名函数
  1: func add(a, b int) int {
  2: 	return a + b
  3: }
  4: func test(){
  5: 	f1 := add
  6: 	fmt.Printf("type of f1=%T\n", f1)
  7: }
  8: func main() {
  9: 	test()
 10: }
  1: func test_1() {
  2: 	f1 := func(a, b int) int {
  3: 		return a + b
  4: 	}
  5: 	fmt.Printf("type of f1=%T\n", f1)
  6: }

defer中使用匿名函数,注意下面两种区别

  1: func test_2() {
  2: 	var i int = 0
  3: 	defer fmt.Printf("i=%d\n", i) // defer里i=0传进去了
  4: 	i = 100
  5: 	return 
  6: }
  7: >>> i = 0
  8: 
  9: func test_3() {
 10: 	var i int = 0
 11: 	defer func() {
 12: 		fmt.Printf("defer i=%d\n", i)
 13: 	} ()
 14: 	i = 100
 15: 	return 
 16: }
 17: >>> defer i=100

函数作为参数

  1: func add(a, b int) int {
  2: 	return a + b
  3: }
  4: 
  5: func test_c(a, b int32) int32 {
  6: 	return a * b
  7: }
  8: 
  9: func sub(a, b int) int {
 10: 	return a - b
 11: }
 12: 
 13: func calc(a, b int,op func(int, int) int) int {
 14: 	return op(a, b)
 15: }
 16: 
 17: func test_4() {
 18: 	sum := calc(100, 300, add)
 19: 	sub := calc(100, 300, sub)
 20: 	su := calc(100, 300, test_c)
 21: 	fmt.Printf("sum=%d sub=%d\n", sum, sub)
 22: }
 23: 

闭包

即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。

例子1:

  1: package main
  2: import "fmt"
  3: 
  4: func add(base int) func(int) int {
  5: 	return func(i int) int {
  6: 		base += i
  7: 		return base
  8: 	}
  9: }
 10: func main() {
 11: 	tmp1:= add(10)
 12: 	fmt.Println(tmp1(1), tmp1(2), tmp1(3))
 13: 	tmp2:= add(100)
 14: 	fmt.Println(tmp2(1), tmp2(2), tmp2(3))
 15: }
 16: >>> 11 13 16
 17: 101 103 106

例子2:

  1: package main
  2: import (
  3: 	"fmt"
  4: 	"strings"
  5: )
  6: 
  7: func makeSuffix(suffix string) func(string) string {
  8: 	return func(name string) string {
  9: 		if !strings.HasSuffix(name, suffix) {
 10: 			return name + suffix
 11: 		}
 12: 		return name
 13: 	}
 14: }
 15: func main() {
 16: 	func1 := makeSuffixFunc(".bmp")
 17: 	func2 := makeSuffixFunc(".jpg")
 18: 	fmt.Println(func1("test"))
 19: 	fmt.Println(func2("test"))
 20: }
 21: 
 22: >>> test.bmp
 23: test.jpg

用python3来写就是这样(比较容易理解)

  1: def makeSuffix(suffix):
  2: 	
  3: 	def func(name):
  4: 		if  not name.endswith(suffix):
  5: 			return name + suffix
  6: 	return func
  7: func = makeSuffix(".bmg")
  8: print(func("test"))

例子3:

  1: func calc(base int) (func(int) int, func(int) int) {
  2: 	add:= func(i int) int {
  3: 		base += i
  4: 		return base
  5: 	}
  6: 	sub:= func(i int) int {
  7: 		base -= i
  8: 		return base
  9: 	}
 10: 	return add, sub
 11: }
 12: 
 13: func main() {
 14: 	f1, f2 := calc(10)
 15: 	fmt.Println(f1(1), f2(2))
 16: 	fmt.Println(f1(3), f2(4))
 17: 	fmt.Println(f1(5), f2(6))
 18: 	fmt.Println(f1(7), f2(8))
 19: }
 20: 
 21: >>> 11 9
 22: 12 8
 23: 13 7
 24: 14 6

闭包的意义

返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域

在多线程下的闭包的副作用:(了解就行了)
  1: package main
  2: 
  3: import (
  4: 	"fmt"
  5: 	"time"
  6: )
  7: func main() {
  8: 	for i:=0;i<5;i++ {
  9: 		go func(){
 10: 			fmt.Println(i)
 11: 		} ()
 12: 	}
 13: 	time.Sleep(time.Second*1)
 14: }
几次的输出结果你会发现不但数值不是固定的,而且居然还会打印出5。本来循环在i=5是就停止了,但是协程搞了鬼,这个后面再讲。

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
go的堆排序发布时间:2022-07-10
下一篇:
Go语言操作MySQL发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap