谈一谈Go的函数function的使用方法
2017-12-13 14:18
274 查看
函数是基本的代码块,用于执行一个任务。Go 语言最少有个 main() 函数。你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。函数声明告诉了编译器函数的名称,返回类型,和参数。Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数字,则返回数组中包含的函数个数。
自定义函数
输出:
myfun里输出,这是值传递 2
main里输出,这是值传递 1
输出:
myfun里输出,这是地址传递 2
main里输出,这是地址传递 2
函数赋值
输出:
函数类型
匿名函数
输出:
匿名函数
闭包
输出:
0xc042048080
0xc042048080
11
0xc042048080
12
不定长传参
输出:
GO [1 2 3 4 5 6 7 8 9]
defer的使用(GO里的“析构函数“)
输出:
a
c
b
没有匿名函数,就没有使用闭包
输出:
4
3
2
1
0
有匿名函数,即使用闭包
输出:
5
5
5
5
5
自定义函数
package main import ( "fmt" ) //值拷贝(值传递)、地址拷贝(地址传递) func main() { a := 1 myfun(a) fmt.Println("main里输出,这是值传递", a) } func myfun(a int) { a = 2//值传递不会改变原来的值 fmt.Println("myfun里输出,这是值传递", a) }
输出:
myfun里输出,这是值传递 2
main里输出,这是值传递 1
package main import ( "fmt" ) //值拷贝(值传递)、地址拷贝(地址传递) func main() { a := 1 myfun(&a) fmt.Println("main里输出,这是地址传递", a) } func myfun(a *int) { *a = 2 //地址传递会改变原来的值 fmt.Println("myfun里输出,这是地址传递", *a) }
输出:
myfun里输出,这是地址传递 2
main里输出,这是地址传递 2
函数赋值
package main import ( "fmt" ) func main() { a := A //a变成了函数类型 a() } func A() { fmt.Println("函数类型") }
输出:
函数类型
匿名函数
package main import ( "fmt" ) func main() { a := func() { fmt.Println("匿名函数") } a() }
输出:
匿名函数
闭包
package main import ( "fmt" ) func main() { f := closure(10) fmt.Println(f(1)) fmt.Println(f(2)) } //闭包可以使局部变量递增 //因为打印出的3次x的地址都是一样的,所以他们指向同一个x地址,不是值得拷贝,而是指向x的原始地址 func closure(x int) func(y int) int { fmt.Printf("%p\n", &x) return func(y int) int { fmt.Printf("%p\n", &x) return x + y } }
输出:
0xc042048080
0xc042048080
11
0xc042048080
12
不定长传参
package main import ( "fmt" ) func main() { A("GO", 1, 2, 3, 4, 5, 6, 7, 8, 9) } //不定长变参,注意的是当有多种类型的参数时,不定长参数应该写在最后面 func A(s string, a ...int) { //其实a就是一个slice fmt.Println(s, a) }
输出:
GO [1 2 3 4 5 6 7 8 9]
defer的使用(GO里的“析构函数“)
package main import ( "fmt" ) func main() { fmt.Println("a") //注意的是:函数体执行结束后按照调用顺序的相反顺序逐个执行,所以先输出c,再输出b defer fmt.Println("b") defer fmt.Println("c") }
输出:
a
c
b
没有匿名函数,就没有使用闭包
package main import ( "fmt" ) func main() { for i := 0; i < 5; i++ { defer fmt.Println(i)//i作为参数传入,则就是当前循环时i值的拷贝,由于defer是倒序执行的,即从4开始,一直到0 } }
输出:
4
3
2
1
0
有匿名函数,即使用闭包
import ( "fmt" ) func main() { for i := 0; i < 5; i++ { //如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址 //为什么5次输出都是5? //因为i一直都是作为引用,作为局部变量i,而上个例子则是作为参数传进去,所以运行到defer时就对i的值进行了拷贝,所以会输出4,3,2,1,0,而现在这个i是作为地址的引用,引用了局部变量,所以退出for循环体的时候就变成了5,而在这个匿名函数return的时候,就开始执行defer语句,那这时defer就是引用i等于3的情况,因为for循环了5次,类似于for里有5个defer表达式,那么就会打印出5个5,这个就是defer与匿名函数、以及在闭包里使用注意的地方。 defer func() { fmt.Println(i) }() } }
输出:
5
5
5
5
5
相关文章推荐
- Go实战--go中函数(function)和方法(method)的使用(The way to go)
- MySQL 的存储过程 procedure 与 函数 function 的区别和使用方法
- Function 之 Read_Text 函数的使用方法
- MySQL 的存储过程 procedure 与 函数 function 的区别和使用方法
- 谈一谈Go的切片Slice的使用方法
- php使用function_exists判断函数可用的方法
- 谈一谈Go的接口interface的使用方法
- 谈一谈Go的结构体struct的使用方法
- MySQL 的存储过程 procedure 与 函数 function 的区别和使用方法
- php使用function_exists判断函数可用的方法
- go语言使用go-sciter创建桌面应用(三) 事件处理,函数与方法定义,go与tiscript之间相互调用
- 在form中调用另一个form的方法,函数:fnd_function.execute 如何在form1中调用form2呢?可以使用函数fnd_function.execute。其函数定义如下: fn
- 谈一谈Go的方法method的使用方法
- 平时在做ASP.NET项目里经常使用的一些函数和方法
- ShellExecute()函数使用方法集锦
- escape()和unescape()函数的使用方法
- 子类重载父类的非虚成员函数是否对从父类中继承且使用该成员函数的方法的行为产生影响
- Oracle分析函数RANK(),ROW_NUMBER(),LAG()等的使用方法(转载)
- c++中函数指针的使用方法
- 平时在做ASP.NET项目里经常使用的一些函数和方法