【Go基础】函数
函数
函数
- 基本介绍
- 匿名函数
- 函数闭包
- 相关资料
基本介绍
基础格式形如:
func function_name ([parameter list]) [return_types] {
函数体
}
func
:function的缩写,是定义函数的关键字。function_name
:函数名。[parameter_lists]
:函数列表,可以有0个或多个。[return_types]
:返回值类型,可以有0个或多个返回值。
示例一:基操
import “fmt”
func main() {
var v = add(1, 2)
fmt.Println("v = ", v) // 输出:a2 = 10
}
func add(a int, b int) int {
return a + b
}
示例二:如果相邻的参数类型相同,则可以采用简便写法
import (
"fmt"
"strconv"
)
func main() {
fmt.Println(hello(1, 2, "Justry", "Deng")) // 输出:3JustryDeng
}
func hello(a, b int, c, d string) string {
// strconv.Itoa的作用是:将int转换为tring
return strconv.Itoa(a+b) + c + d
}
示例三:多返回值
import (
"fmt"
)
func main() {
v1, v2 := hello(0, 0)
fmt.Println(v1, "\t", v2) // 输出:100 -100
}
func hello(a, b int) (int, int) {
return1 := a + 100
return2 := b - 100
return return1, return2
}
示例四:无返回值
import (
"fmt"
)
func main() {
hello("邓沙利文")
}
func hello(name string) {
fmt.Println("hello " + name) // 输出:hello 邓沙利文
}
示例五:形参传递变量的地址(,在方法内部可修改外部变量的值)
提示:对照组是没使用地址变量前的效果,实验组是使用地址变量后的效果
对照组
import (
"fmt"
)
func main() {
a := 1
add(a)
fmt.Println("调用add后,值为", a) // 输出:调用add后,值为 1
}
func add(v int) {
v++
fmt.Println("add方法内部,值为", v) // 输出:add方法内部,值为 2
}
实验组
import (
"fmt"
)
/** * 提示:值变量前加上&, 即代表值变量的地址 * 地址变量前加上*, 即代表地址变量的地址值 */
func main() {
a := 1
add(&a)
fmt.Println("调用add后,值为", a) // 输出:调用add后,值为 2
}
func add(v *int) {
*v++
fmt.Println("add方法内部,值为", *v) // 输出:add方法内部,值为 2
}
注:在值变量前加上
&
,可以得到值变量的地址;在地址变量前加上*
,可代表内存单元,即:指向该地址的值变量的值
匿名函数
匿名函数即没有函数名字的函数
示例一:基操
import (
"fmt"
)
func main() {
a := func(v int) int {
return v + 1
}(99)
fmt.Println("a = ", a) // 输出:a = 100
}
提示:匿名函数体后,带小括号才代表该匿名函数被调用
示例二:匿名函数作为参数
import (
"fmt"
)
func main() {
a, b := 300, 500
fmt.Println("a + b = ", addOrSub(a, b, add)) // 输出:a + b = 800
fmt.Println("a - b = ", addOrSub(a, b, sub)) // 输出:a - b = -200
}
func add(a, b int) int {
return a + b
}
func sub(a, b int) int {
return a - b
}
/* 其中变量f的类型是函数 func(v1, v2 int) int, 即:所有满足func(v1, v2 int) int格式要求的函数,都可以作为该处的参数 */
func addOrSub(a, b int, f func(v1, v2 int) int) int {return f(a, b)
}
函数闭包
所谓闭包就是在函数内部,可以读取父函数的变量
代码示例:
func getSequence() func() int {
i := 0
return func() int {
i++
return i
}
}
说明:
getSequence()
中的内部结构,i在该函数内部定义,属于局部变量,但是在返回的匿名函数中对这个i进行了引用(闭包),并且把这个i进行了返回。每当getSequence()
被调用时实际得到的是以func() int
为原型的匿名函数,由于该匿名函数对i的引用一直存在,因此本来是临时变量的i在getSequence()
返回后并不会被释放,内存分析如图:这个
getSequence
函数的作用很有意思,在通过调用getSequence
得到的匿名函数每次调用时,都会促使i的值自增,这样就得到了类似数据库中的自增序列那样的功能,示例:import (
"fmt"
)
func main() {
nextnumber := getSequence()
fmt.Println(nextnumber()) // 输出:1
fmt.Println(nextnumber()) // 输出:2
fmt.Println(nextnumber()) // 输出:3
}
func getSequence() func() int {
i := 0
return func() int {
i++
return i
}
}
- 加深理解:如果再用一个
f := getSequence()
,f
和nextnumber
交替使用,彼此会互相影响吗?答案是不会。虽然getSequence()
被调用时i是不释放的,但是不同的getSequence()
调用时对应的i的内存地址是不同的,也就是说2此调用会产生2个独立的i,不会彼此影响,内存分析如图: 用代码验证一下:
import (
"fmt"
)
func main() {
nextnumber := getSequence()
fmt.Println(nextnumber()) // 输出:1
fmt.Println(nextnumber()) // 输出:2
fmt.Println(nextnumber()) // 输出:3
f := getSequence()
fmt.Println(f()) // 输出:1
fmt.Println(f()) // 输出:2
fmt.Println(f()) // 输出:3
}
func getSequence() func() int {
i := 0
return func() int {
i++
return i
}
}
^_^ 整理自《Go语言区块链应用开发从入门到精通》高野 编著
^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng
还没有评论,来说两句吧...