golang匿名函数的活用

golang匿名函数的活用



回调函数


package main

import "fmt"

type FuncType func(int, int) int

// Calc 计算函数
func Calc(a, b int, fTest FuncType) (result int) {
	result = fTest(a, b)
	return
}

func main()  {
	x, y := 2, 2
	// Add
	// 回调函数是匿名函数
	addResult := Calc(x, y, func(a int, b int) int {
		return a + b
	})
	// 回调函数是匿名函数
	subResult := Calc(x, y, func(a int, b int) int {
		return a - b
	})
	fmt.Println("addResult: ", addResult)
	fmt.Println("subResult: ", subResult)
}

运行结果:

addResult:  4
subResult:  0

闭包


我们使用一个特殊的情况来举例子,顺便巩固一下并发的知识。

请看以下代码,是golang并发中的闭包:

package main

import (
	"fmt"
	"runtime"
	"sync"
)

func main()  {
	runtime.GOMAXPROCS(runtime.NumCPU())

	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			fmt.Println(i)
			wg.Done()
		}()
	}
	wg.Wait()
}

运行结果:

5
5
5
5
5

造成这一输出结果的原因是启动一个goroutine的时间慢于主goroutine中循环的执行时间。
这个时候你可能会想到使用循环延时的办法,但是一旦这样做,就失去了并发优势。

所以一般采用以下两个方法:

  1. 将循环变量作为参数传递给匿名函数,原因在于传参的速度几乎是瞬时的,且在启动goroutine前执行。

    for i := 0; i < 5; i++ {
    		wg.Add(1)
    		go func(i int) {
    			fmt.Println(i)
    			wg.Done()
    		}(i)
    	}
    // 4
    // 2
    // 3
    // 0
    // 1
    
  2. 使用同名变量保留当前循环变量的状态

    for i := 0; i < 5; i++ {
    		wg.Add(1)
    		i := i
    		go func() {
    			fmt.Println(i)
    			wg.Done()
    		}()
    	}
    // 0
    // 1
    // 3
    // 4
    // 2
    
    

其它用法


定义时调用匿名函数

func sayHi()  {
	func() {
		fmt.Println("hello")
	}()
}

func main()  {
	sayHi()
}

将匿名函数复制给变量

func main()  {
	var sayHi func() = func() {
		fmt.Println("hello")
	}
	sayHi()
}

带有return的匿名函数

func sayHi()  {
	greet := func() string {
		return "hello"
	}
	fmt.Println(greet())
}

func main()  {
	sayHi()
}

遍历对象数组时做一些回调操作


在学习godis的时候,其中有一个数据引擎接口:EmbedDB。里面有一个遍历当前数据库所有内容的函数:forEach,该函数的形参列表中有一个匿名函数,可以在函数调用的时候,做一些回调操作,我觉得很巧妙。于是就有了下面的例子,该例子没有任何意义,仅仅是展现匿名函数的该种用法。

package main

import "fmt"

type function interface {
	forEach(func(i int))
}

// Array 数组结构体实现了接口
type Array struct {
	array []int
	length int
}

func (a *Array) forEach(callBack func(i int)) {
	for i := 0; i < a.length; i++ {
		callBack(i)
	}
}
func (a *Array) Add(value int) {
	a.array = append(a.array, value)
	a.length++
}
func NewArray() Array {
	return Array{
		make([]int, 0),
		0,
	}
}

func main()  {
	arr := NewArray()
	arr.Add(1)
	arr.Add(2)
	arr.Add(3)

	// 将每个元素++
	arr.forEach(func(i int) {
		arr.array[i]++
	})
	// 打印每个元素
	arr.forEach(func(i int) {
		fmt.Println(arr.array[i])
	})
}

输出结果:

2
3
4

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值