Go语言中支持:函数、匿名函数和闭包
- 定义函数使用func关键字
func 函数名(参数)(返回值){
函数体
}
注意:函数名由字母、数字、下划线组成,但不能以字母开头。在同一个包内,函数名不能重名
//求两个数的和
func sumFn(x int, y int) int {
sum := x + y
return sum
}
func main(){
result := sumFn(12, 3)
fmt.Println(result)//15
}
函数参数的简写(只能简写前面的)
func subFn(x, y int) int {
return x - y;
}
函数的可变参数
可变参数其实是一个切片,通过在参数名后加
...
来标记,可变参数与固定参数结合使用时只能放在后面
//求n个参数的和
func sumFn1(x ...int)int{
fmt.Printf("%v--%T", x, x)
sum := 0
for _,v := range x {
sum += v
}
return sum
}
//[12 15 8 0]--[]int
func main(){
result := sumFn1(12,15,8,0)
fmt.Println(result)//35
}
注意,函数有返回值时,必须指定其类型
return关键字一次可以返回多个值
func calc(x, y int) (int, int){
sum := x + y
sub := x - y
return sum, sub
}
func main(){
sum,sub := calc(10, 2)
fmt.Println(sum, sub)//12 8
}
返回值命名:函数定义时可以给返回值命名,并在函数体中直接使用这些变量,最后通过return关键字直接返回
func calc(x, y int) (sum int, sub int){
//或func calc(x, y int) (sum, sub int){
sum = x + y
sub = x - y
return
}
封装一个简单的选择排序(升序)
func sortIntAsc(slice []int) []int {
for i := 0; i < len(slice); i++ {
for j := i + 1; j < len(slice); j++ {
if slice[i] > slice[j] {
temp := slice[i]
slice[i] = slice[j]
slice[j] = temp
}
}
}
return slice
}
func main(){
var sliceA = []int{1, 5, 3, 0}
arr := sortIntAsc(sliceA)
fmt.Println(arr)//[0 1 3 5]
}
对map按照key的ASCII进行升序排序
func mapSort(map1 map[string]string) string {
var sliceKey []string
//把map对象的key放到切片中
for k, _ := range map1 {
sliceKey = append(sliceKey, k)
}
//对key进行升序排序
sort.Strings(sliceKey)
//循环拼接字符串
var str string
for _, v := range sliceKey {
str += fmt.Sprintf("%v=>%v ", v, map1[v])
}
return str
}
func main(){
m1 := map[string]string{
"username":"zhangsan",
"age":"20",
"sex":"男",
}
str := mapSort(m1)
fmt.Println(str)
}
//age=>20 sex=>男 username=>zhangsan
函数变量作用域(同C语言)
- 全局变量
定义在函数外部的变量,在整个程序的运行周期内都有效
- 局部变量
在函数内部定义的变量,无法在外部使用
定义函数类型
使用type关键字来定义一个calulation类型的函数,它接收两个int类型的参数,并返回一个int类型的返回值
type calulation func(int, int) int
定义一个calc的类型
type calc func(int, int) int
type myInt int
func add(x, y int) int {
return x + y
}
func test(){
fmt.Println("test...")
}
func main(){
var c clac
c = add
fmt.Printf("c的类型:%T", c) //c的类型:main.calc
//c = test//这里报错了,因为test不满足calc的类型
fmt.Println(c(10, 5)) //15
f := add
fmt.Printf("f的类型%T\n", f) //f的类型:func(int, int) int
fmt.Println(f(15,5))//20
var num1 int = 10
var num2 myInt = 20
fmt.Printf("num1的类型%T--num2的类型%T\n", num1, num2)
//num1的类型int--num2的类型main.myInt
fmt.Println(num1 + int(num2)) // 30
}
函数作为另一个函数的参数
type calcType func(int, int) int
func add(x, y int)int {
return x + y
}
func calc(x, y int, cb calcType) int {
return cb(x, y)
}
func main(){
fmt.Println(calc(10, 20, add))//30
mult := calc(3, 4, func(x, y int) int{
return x * y
})
fmt.Println(mult)//12
}
匿名函数
匿名函数因为没有函数名,所以不能像普通函数那样调用,所以匿名函数需要保存到某个变量活着作为立即执行函数
func add(x, y int) int {
return x + y
}
func sub(x, y int) int {
return x - y
}
//定义一个方法类型
type calcType func(int, int) int
func do (o string) calcType {
switch o {
case "+":
return add
case "-":
return sub
case "*":
return func(x, y int) int {
return x * y
}
default:
return nil
}
}
func main(){
var a = do("+")
fmt.Println(a(4, 8)) //12
b := do("*")
fmt.Println(b(3, 4)) //12
}
函数的递归调用(与C一致,尽量避免递归)
函数的闭包
闭包是指有权访问另一个函数作用域中的变量的函数,可以让一个变量常驻内存且不污染全局变量。
func adder() func() int {
var i = 10 //常驻内存,不污染全局
return func() int {
return i + 1
}
}
func adder2() func(y int) int {
var i = 10
return func(y int) int {
i += y
return i
}
}
func main(){
var fn = adder()
fmt.Println(fn())//11
fmt.Println(fn())//11
fmt.Println(fn())//11
var fn2 = adder2()
fmt.Println(fn(10))//20
fmt.Println(fn(2))//22
fmt.Println(fn(1))//23
}
注意:由于闭包的作用域中返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。过度使用闭包会导致性能下降,所以,在非必要时不建议使用闭包。
有疑问加站长微信联系(非本文作者)