你懂写日志的策略吗?不懂,就不是合格的服务器工程师
在平时我们开发程序的时候,我们经常会想把一些数据作为日志来记录,尤其是我们做服务端的,日志往往是特别重要的,不管是我们后面的拍错,还是查看程序的运行状态,都需要借助日志来分析。
但是,实际开发中,往往会借助第三方的库或者让是开源库的方式。但是,在平时小型的项目中的话,这么做往往是应了那句话,“杀鸡焉用宰牛刀”;平时我们得小项目或者是测试的demo,我们可以用简单的语句去写日志,并记录,往往显放入特别重要。
经常写程序的朋友们,会看到这样的代码:
#define LOG(format,...)
我们想过这么写的意义或者是这么写的好处吗?我们一步一步来看一下这类型的语句。
#define LOG(format, ...) fprintf(stdout, format, __VA_ARGS__)
其中,...表示可变参数列表,__VA_ARGS__在预处理中,会被实际的参数集(实参列表)所替换。
我们来看一个例子:
#include<iostream>
#include<stdio.h>
using namespace std;
#define LOG(format,...)fprintf(stdout,format,__VA_ARGS__)
int main()
{
LOG("%s\n","hello");
return 0;
}
看一下结果:
hello
我们发现,我们最终想要打印的东西,会显示在终端上面。
#define LOG(format, args...) fprintf(stdout, format, args)
args在预处理过程中,和上面很类似,会被实际的参数集所替换。相比较来说,只是参数的符号有变。需要注意的是,上述两种方式的可变参数不能省略,当然也可以传一个空参数进去,。
实例:
#include<iostream>
#include<stdio.h>
using namespace std;
#define LOG(format,args...)fprintf(stdout,format,args)
int main()
{
LOG("%s world\n","hello");
return 0;
}
结果:
hello world
接下来我么说一下#和## 之间的区别:
# :把参数字符串化
##:将两个参数连为一个整体
看一下例子:
#include <iostream>
#include <cstdlib>
// 测试不带 # 号的效果
#define NO_NUMBER_SIGN(x) x
// 测试一个 # 号的效果
#define SINGLE_NUMBER_SIGN(x) #x
// 测试两个 # 号的效果
#define DOUBLE_NUMBER_SIGN(x, y) x##y
int main()
{
// 测试不带 # 号的效果:hello 不加双引号报错(error C2065: “hello”: 未声明的标识符)
std::cout << NO_NUMBER_SIGN("hello") << std::endl;
// 测试一个 # 号的效果:world 加不加双引号都可以,因为 # 将其字符串化
std::cout << SINGLE_NUMBER_SIGN(world) << std::endl;
// 测试两个 # 号的效果:连接两个对象
std::cout << DOUBLE_NUMBER_SIGN("wang", "ying") << std::endl;
system("pause");
return 0;
}
结果:
hello
world
wangying
“##”连接符号的用法,“##”的作用是对token进行连接,在上面的format,args,__VA_ARGS都可以看作是token,如果token为空,“##”则不进行连接,所以允许省略可变参数。
上面两个式子我们可以看一下:
#define LOG(format, ...) fprintf(stdout, format, ##__VA_ARGS__)
#define LOG(format, args...) fprintf(stdout, format, ##args)
看看案例:
#include<iostream>
#include<stdio.h>
using namespace std;
#define LOG(format,args...)fprintf(stdout,"everyone"format,##args)
#define LOG2(format,...)fprintf(stdout,"everyone"format,##__VA_ARGS__)
int main()
{
LOG("%s \n","args");
LOG2("%s \n","VA_ARGS");
return 0;
}
结果:
everyoneargs
everyoneVA_ARGS
在平时写代码的时候,我们也可以用宏来控制日志是否使用。
#include<iostream>
#include<stdio.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
#define LOG(format,args...)fprintf(stdout,"everyone"format,##args)
#define LOG2(format,...)fprintf(stdout,"everyone"format,##__VA_ARGS__)
#endif
int main()
{
LOG("%s \n","args");
LOG2("%s \n","VA_ARGS");
return 0;
}
欢迎大家关注我的公众号:CPP后台服务器开发
我们一起加油,一起成长。