oam 纯度_我编程中的纯度:Go中的函数

oam 纯度

在Javascript世界中,纯函数经常被大肆宣传,这可能是由于前端应用程序中的状态丰富。 尽管纯函数有其缺点(即带来不便,可能存在大量参数列表),但我认为应尽可能合理地使用它们,并且我想关注Go中的纯函数。

什么是纯函数?

根据Wikipedia所述 ,Pure函数具有以下属性:

  1. 对于相同的参数,返回值是相同的(局部静态变量非局部变量 ,可变引用参数或来自I / O设备的输入流无变化)。
  2. 它的评估没有副作用 (本地静态变量,非本地变量,可变引用参数或I / O流不会发生突变)。

这意味着作为开发人员,我知道两件重要的事情:

  1. 当我调用一个纯函数时,每次都会得到相同的精确结果
  2. 调用纯函数后,我的程序将处于与调用前相同的状态(时间会流逝,并且我将已分配函数的结果)

由于这些特性,纯函数使应用程序简单。 众所周知,简单的应用程序通常会更快,更易于测试和调试,并且更不易出错。

Go(golang)中的示例

totalCounted :=map [ string ] int {}

func countNamesInText (text string ) {
	total := 0
	const name = getNameFromDatabase()
	for _, word := range strings.Split(text, " " ) {
		if word == mention {
			total++
		}
	}
	totalCounted[name] = total
}

此功能不纯,原因有两个。 让我们检查每个。

1.通过调用countNamesInText()改变程序状态

我们应该通过return语句返回数据,而不是将全局变量变异为“返回”数据给调用者的方法。 我们可以假设这样做是因为在程序的其他地方存储计数映射是个好主意,但是最好在计数功能之外处理状态管理:

func countNamesInText (text string ) int {
	totalCounted := 0
	const name = getNameFromDatabase()
	for _, word := range strings.Split(text, " " ) {
		if word == mention {
			totalCounted++
		}
	}
	return totalCounted
}

更好的是,此功能更“纯净”,因为它不会更改应用程序的状态。

2.数据库参数

我们的函数仍然不纯正,因为从数据库中检索了影响函数调用结果的“名称”值。 为了使我们的函数具有确定性,该值应改为作为参数传递。

目前,如果我们编写了测试:

func TestCountNamesInText (t *testing.T) {
	assert.Equal(t, 2 , countNamesInText( "this word here" ))
}

它不能始终如一地工作。 如果未设置数据库,或者数据库被篡改,我们的测试将失败。 这使它成为一个不好的测试,并且由于功能不纯而我们写了不好的测试。

让我们进一步净化一下:

func countNamesInText (text, name string ) int {
	totalCounted := 0
	for _, word := range strings.Split(text, " " ) {
		if word == mention {
			totalCounted++
		}
	}
	return totalCounted
}

我们的功能是纯洁的! 现在我们可以进行良好的测试:

func TestCountNamesInText (t *testing.T) {
	assert.Equal(t, 1 , countNamesInText( "this word here" , "this" ))
}

如果我们包括状态管理和数据库调用在内,现在我们的应用程序看起来将是什么样子:

totalCounted :=map [ string ] int {}
name := getNameFromDatabase()
totalCounted[name] = countNamesInText( "some name in here" , name)

谢谢阅读!

莱恩·瓦格纳@wagslane

在Qvault学习: https ://classroom.qvault.io

先前发表于 https://qvault.io/2019/10/30/purity-in-my-programming-please/

翻译自: https://hackernoon.com/purity-in-my-programming-pure-functions-in-go-c21m3u2z

oam 纯度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一句句解释分析细致讲解一下这段代码void netconf_entry(void) { int state = 0; int event = 0; UINT8 * pPacket = NULL; UINT32 dataLen = 0; char *pData = NULL; UINT8 ret = 0; struct np_module netopeer_module; struct np_module server_module; memset(&netopeer_module,0,sizeof(struct np_module)); memset(&server_module,0,sizeof(struct np_module)); state = Ros_GetCurState(); event = Ros_GetMsgId(); switch( state ) { case NETCONF_PROCESS_INIT: switch( event ) { case MSG_MasterPowerOn: case MSG_SlavePowerOn: //printf("netconf_entry MSG_SlavePowerOn\n"); Ros_SetNextState(NETCONF_PROCESS_RUNNING); break; case MSG_INIT_PROTOCOL_OK: Ros_SetNextState(NETCONF_PROCESS_RUNNING); break; default: break; } break; case NETCONF_PROCESS_RUNNING: switch( event ) { case MSG_DriverOK: netconf_init(); break; case MSG_NETCONF_TO_DCN: nc_verb_verbose("netconf_entry recv netconf to dcn msg\n"); break; case MSG_ALARM_TO_NETCONF: NcProcessAlarmMsg(); break; case MSG_LIBNETCONF_TO_NETOPEER: ncRcvLibnetconfMsgProc(); break; case MSG_NETCONF_LLDP_TIMER: Ros_SetTimer(netconfLLDPTimerID, NETCONF_MSG_TIME_LLDP, 0); ncLldpchange(); break; case MSG_NETCONF_15MIN_PERF_TIMER: Ros_SetTimer(netconf15MINPerfTimerID, NETCONF_MSG_15MIN_TIME_PERF, 0); packageOptInfo15Min(); packageIfStatisInfo15Min(); break; case MSG_NETCONF_24H_PERF_TIMER: Ros_SetTimer(netconf24hPerfTimerID, NETCONF_MSG_24H_TIME_PERF, 0); packageOptInfo24H(); packageIfStatisInfo24H(); break; case MSG_NETCONF_MEM_CHECK_TIMER: printS("MSG_NETCONF_MEM_CHECK_TIMER TIMEROUT\n"); memory_line_check(0); break; case MSG_NETCONF_TIMER: oam_perf_netconf_show_value_entry(); break; default: break; } break; default: break; } return EXIT_SUCCESS; }
07-14
下面是对这段代码的逐句解释和分析: ```c++ void netconf_entry(void) { int state = 0; int event = 0; UINT8 * pPacket = NULL; UINT32 dataLen = 0; char *pData = NULL; UINT8 ret = 0; struct np_module netopeer_module; struct np_module server_module; memset(&netopeer_module,0,sizeof(struct np_module)); memset(&server_module,0,sizeof(struct np_module)); ``` 这段代码定义了一个名为netconf_entry的函数,没有参数,返回类型为void。 接下来,定义了一系列变量,包括state和event(int类型)、pPacket(UINT8指针类型)、dataLen(UINT32类型)、pData(char指针类型)和ret(UINT8类型)。 然后,定义了两个结构体变量netopeer_module和server_module,并使用memset函数将其内容初始化为0。 ```c++ state = Ros_GetCurState(); event = Ros_GetMsgId(); switch( state ) { case NETCONF_PROCESS_INIT: switch( event ) { case MSG_MasterPowerOn: case MSG_SlavePowerOn: //printf("netconf_entry MSG_SlavePowerOn\n"); Ros_SetNextState(NETCONF_PROCESS_RUNNING); break; case MSG_INIT_PROTOCOL_OK: Ros_SetNextState(NETCONF_PROCESS_RUNNING); break; default: break; } break; case NETCONF_PROCESS_RUNNING: switch( event ) { case MSG_DriverOK: netconf_init(); break; case MSG_NETCONF_TO_DCN: nc_verb_verbose("netconf_entry recv netconf to dcn msg\n"); break; case MSG_ALARM_TO_NETCONF: NcProcessAlarmMsg(); break; case MSG_LIBNETCONF_TO_NETOPEER: ncRcvLibnetconfMsgProc(); break; case MSG_NETCONF_LLDP_TIMER: Ros_SetTimer(netconfLLDPTimerID, NETCONF_MSG_TIME_LLDP, 0); ncLldpchange(); break; case MSG_NETCONF_15MIN_PERF_TIMER: Ros_SetTimer(netconf15MINPerfTimerID, NETCONF_MSG_15MIN_TIME_PERF, 0); packageOptInfo15Min(); packageIfStatisInfo15Min(); break; case MSG_NETCONF_24H_PERF_TIMER: Ros_SetTimer(netconf24hPerfTimerID, NETCONF_MSG_24H_TIME_PERF, 0); packageOptInfo24H(); packageIfStatisInfo24H(); break; case MSG_NETCONF_MEM_CHECK_TIMER: printS("MSG_NETCONF_MEM_CHECK_TIMER TIMEROUT\n"); memory_line_check(0); break; case MSG_NETCONF_TIMER: oam_perf_netconf_show_value_entry(); break; default: break; } break; default: break; } return EXIT_SUCCESS; } ``` 接下来,代码根据当前状态(state)和事件(event)进行switch语句的判断。 如果state为NETCONF_PROCESS_INIT,根据event的不同进行不同的操作。如果event是MSG_MasterPowerOn或MSG_SlavePowerOn,则将下一个状态设置为NETCONF_PROCESS_RUNNING。如果event是MSG_INIT_PROTOCOL_OK,则同样将下一个状态设置为NETCONF_PROCESS_RUNNING。 如果state为NETCONF_PROCESS_RUNNING,根据event的不同进行不同的操作。如果event是MSG_DriverOK,则调用netconf_init函数。如果event是MSG_NETCONF_TO_DCN,则打印一条调试信息。如果event是MSG_ALARM_TO_NETCONF,则调用NcProcessAlarmMsg函数。如果event是MSG_LIBNETCONF_TO_NETOPEER,则调用ncRcvLibnetconfMsgProc函数。如果event是MSG_NETCONF_LLDP_TIMER,则设置一个定时器,并调用ncLldpchange函数。如果event是MSG_NETCONF_15MIN_PERF_TIMER,则设置一个定时器,并依次调用packageOptInfo15Min和packageIfStatisInfo15Min函数。如果event是MSG_NETCONF_24H_PERF_TIMER,则设置一个定时器,并依次调用packageOptInfo24H和packageIfStatisInfo24H函数。如果event是MSG_NETCONF_MEM_CHECK_TIMER,则打印一条信息,并调用memory_line_check函数。如果event是MSG_NETCONF_TIMER,则调用oam_perf_netconf_show_value_entry函数。 最后,函数返回EXIT_SUCCESS(整数值,表示成功)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值