c++日志库实战——spdlog,是不是感觉log4cxx有点笨重,不妨试一试spdlog

2023-11-03

背景

在最近新入职同事的推荐下,作者在一个小工具中学习和使用了spdlog,且已发布到线上运行,以下是学习记录。

更新记录

  • 2021.05.14 增加封装spdlog头文件,快速集成到项目
  • 2021.05.14 通过vcpkg编译安装,1秒集成使用,推荐

spdlog是什么

Fast C++ logging library
按照官方介绍,是一个高性能的C++日志组件,支持跨平台,兼容 C++11。原来项目中使用的是log4cxx,我感觉稍微有点笨重,并且很久没有更新了。

在新项目中,我只需要一款轻量级的日志组件,能:

  • 存文件
  • 按照天数切分

快速的浏览了spdlog,满足我的需求,于是开搞!

spdlog快速入门

githubhttps://github.com/gabime/spdlog

以下内容来自spdlog的 README

编译

CMake手动方式

$ git clone https://github.com/gabime/spdlog.git
$ cd spdlog && mkdir build && cd build
$ cmake .. && make -j

PS:使用cmake来编译,cmake 命令会生成makefile。如果机器上没有cmake,请先安装一下,我的cmake3.14.5macos 10.15

meki-mac-pro:~ xuyc$ cmake -version
cmake version 3.14.5

CMake suite maintained and supported by Kitware (kitware.com/cmake).

Vcpkg全自动方式(推荐)

首先,确保安装了vcpkg,可以参见 Github文档

  1. 安装spdlog包
$ vcpkg search spdlog # 搜索
$ vcpkg install spdlog # 下载,编译,VS2017中会自动发现
  1. 配置CMake,使用Vcpkg

附(vcpkg更多install语法):

# windows 下使用静态库(mt运行时)
$ vcpkg install spdlog:x86-windows-static-mt
# windows 下使用静态库(md运行时)
$ vcpkg install spdlog:x86-windows-static-md 

原生用法

#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"

int main() 
{
    spdlog::info("Welcome to spdlog!");
    spdlog::error("Some error message with arg: {}", 1);
    
    spdlog::warn("Easy padding in numbers like {:08d}", 12);
    spdlog::critical("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);
    spdlog::info("Support for floats {:03.2f}", 1.23456);
    spdlog::info("Positional args are {1} {0}..", "too", "supported");
    spdlog::info("{:<30}", "left aligned");
    
    spdlog::set_level(spdlog::level::debug); // Set global log level to debug
    spdlog::debug("This message should be displayed..");    
    
    // change log pattern
    spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");
    
    // Compile time log levels
    // define SPDLOG_ACTIVE_LEVEL to desired level
    SPDLOG_TRACE("Some trace message with param {}", 42);
    SPDLOG_DEBUG("Some debug message");
    
    // Set the default logger to file logger
    auto file_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
    spdlog::set_default_logger(file_logger);            
}

官方的代码大概知道怎么使用spdlog了,点个赞。但是可能会遇到一些问题,下面笔者遇到问题的记录。

实战代码

SpdlogWarper

  1. log.h
#ifndef _LOG_0B0512CC_B1CC_4483_AF05_1914E7F7D4DA_
#define _LOG_0B0512CC_B1CC_4483_AF05_1914E7F7D4DA_

#include <string>
#include <corecrt_io.h>

#ifndef SPDLOG_TRACE_ON
#define SPDLOG_TRACE_ON
#endif

#ifndef SPDLOG_DEBUG_ON
#define SPDLOG_DEBUG_ON
#endif

#ifdef _WIN32
#define __FILENAME__ (strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1):__FILE__)
#else
#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1):__FILE__)
#endif

#include "zim/zim_dll.h"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"

namespace zim {
    class ZIM_DLL_API ZLogger {
      public:
        auto GetLogger() {
            return nml_logger;
        }

        ZLogger();
        ~ZLogger();
        ZLogger(const ZLogger&) = delete;
        ZLogger& operator=(const ZLogger&) = delete;

      private:
        std::shared_ptr<spdlog::logger> nml_logger;
    };
}
ZIM_DLL_API zim::ZLogger& GetInstance();

#define SPDLOG_LOGGER_CALL_(level, ...) GetInstance().GetLogger()->log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__)
#define LogTrace(...)  SPDLOG_LOGGER_CALL_(spdlog::level::trace,__VA_ARGS__)
#define LogDebug(...)  SPDLOG_LOGGER_CALL_(spdlog::level::debug,__VA_ARGS__)
#define LogInfo(...)   SPDLOG_LOGGER_CALL_(spdlog::level::info,__VA_ARGS__)
#define LogWarn(...)   SPDLOG_LOGGER_CALL_(spdlog::level::warn,__VA_ARGS__)
#define LogError(...)  SPDLOG_LOGGER_CALL_(spdlog::level::err,__VA_ARGS__)
#define LogCritical(...) SPDLOG_LOGGER_CALL_(spdlog::level::critical,__VA_ARGS__)
#define LogCriticalIf(b, ...)               \
    do {                                  		    \
			if ((b)) {               			  \
				 SPDLOG_LOGGER_CALL_(spdlog::level::critical,__VA_ARGS__); \
			}                                      \
	} while (0)

#ifdef WIN32
#define errcode WSAGetLastError()
#endif

#endif//_LOG_0B0512CC_B1CC_4483_AF05_1914E7F7D4DA_
  1. Log.cpp
#include "pch.h"
#include "Log.h"

zim::ZLogger& GetInstance() {
    static zim::ZLogger m_instance;
    return m_instance;
}

namespace zim {
    ZLogger::ZLogger() {
        if (::_access("logs", 0) == -1) {
            ::_mkdir("logs");
        }

        //设置为异步日志
        //spdlog::set_async_mode(32768);  // 必须为 2 的幂
        std::vector<spdlog::sink_ptr> sinkList;

#if 1
        auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
        consoleSink->set_level(spdlog::level::debug);
        //consoleSink->set_pattern("[multi_sink_example] [%^%l%$] %v");
        //consoleSink->set_pattern("[%m-%d %H:%M:%S.%e][%^%L%$]  %v");
        consoleSink->set_pattern("%Y-%m-%d %H:%M:%S [%l] [%t] - <%s>|<%#>|<%!>,%v");
        sinkList.push_back(consoleSink);
#endif
        auto dailySink = std::make_shared<spdlog::sinks::daily_file_sink_mt>("logs/log.log", 2, 30);
        dailySink->set_level(spdlog::level::debug);
        sinkList.push_back(dailySink);

        nml_logger = std::make_shared<spdlog::logger>("both", begin(sinkList), end(sinkList));
        //register it if you need to access it globally
        spdlog::register_logger(nml_logger);

        // 设置日志记录级别
#ifdef _DEBUG
        nml_logger->set_level(spdlog::level::trace);
#else
        nml_logger->set_level(spdlog::level::info);
#endif

        //设置当出发 err 或更严重的错误时立刻刷新日志到  disk .
        nml_logger->flush_on(spdlog::level::warn);

        spdlog::set_pattern("%Y-%m-%d %H:%M:%S [%l] [%t] - <%s>|<%#>|<%!>,%v");
        spdlog::flush_every(std::chrono::seconds(2));

    }

    ZLogger::~ZLogger() {
        spdlog::drop_all();
    }
}

使用

#include "Log.h"

int main(){
    LogTrace("trach");
    // 和其他日志库最大的区别所在,也是灵魂所在
    // 自动识别类型,避免%d,%s类型错误,输出不了内容或者崩溃
	LogDebug("cmd_id={},bodyLen={}", 1, 2);
	LogInfo("user_id={},app_id={},domainId={},ip={},port={}", 222, 222, 222, "127.0.0.1", 8888);
    // log.cpp中是flush on Warn,所以,这一条日志打印后,才刷到文件
	LogWarn("bad packet");
	LogError("error");
	
	return 0;
}

常见问题

打印行号

// 先设置日志输出格式
// %s:文件名,my_file.cpp
// %#:行号,123
// %!:函数名,my_func
spdlog::set_pattern("%Y-%m-%d %H:%M:%S [%l] [%t] - <%s>|<%#>|<%!>,%v");

// 使用宏才会有行号
SPDLOG_DEBUG("Some debug message");

spdlog::info("Welcome to spdlog!");

具体见:https://github.com/gabime/spdlog/wiki/3.-Custom-formatting

推荐写法

#define DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__)
#define LOG(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__)
#define WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__)
#define ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__)

DEBUG("debug");
LOG("info");

怎么控制台看不到log

设置默认logger为控制台即可

// 设置默认logger,这里是控制台,所以spdlog::info的内容会输出到控制台
auto console = spdlog::stdout_color_mt("console");
spdlog::set_default_logger(console);

官方代码

#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
void stdout_example()
{
    // create color multi threaded logger
    auto console = spdlog::stdout_color_mt("console");    
    //auto err_logger = spdlog::stderr_color_mt("stderr");    
    spdlog::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");
}

同时输出控制台和文件

  1. 先注册
// 每天2:30 am 新建一个日志文件
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
// 遇到warn flush日志,防止丢失
logger->flush_on(spdlog::level::warn);
  1. 通过宏来同时输出console和文件,注意logger名字和上面的对应。
// spd 带行号的打印,同时输出console和文件
#define DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_DEBUG(spdlog::get("daily_logger"), __VA_ARGS__)
#define LOG(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_INFO(spdlog::get("daily_logger"), __VA_ARGS__)
#define WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_WARN(spdlog::get("daily_logger"), __VA_ARGS__)
#define ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_ERROR(spdlog::get("daily_logger"), __VA_ARGS__)

文件按天分割

#include "spdlog/sinks/daily_file_sink.h"
void daily_example()
{
    // Create a daily logger - a new file is created every day on 2:30am
    auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
}

停止调试log没有写文件?

spdlog为了提高性能,降低对磁盘的写操作,通过flush机制来一次性把日志写入到文件里面持久化。所以如果没有恰当的配置,停止调试或者进程崩溃的时候会有日志丢失的问题。

定时flush到文件:

//每三秒刷新一次
spdlog::flush_every(std::chrono::seconds(3));

遇到error级别,立即flush到文件:

enum level_enum
{
    trace = SPDLOG_LEVEL_TRACE, // 最低
    debug = SPDLOG_LEVEL_DEBUG,
    info = SPDLOG_LEVEL_INFO,
    warn = SPDLOG_LEVEL_WARN,
    err = SPDLOG_LEVEL_ERROR,
    critical = SPDLOG_LEVEL_CRITICAL, // 最高
    off = SPDLOG_LEVEL_OFF,
    n_levels
};

auto logger = spdlog::daily_logger_mt("daily_logger", "log/daily.txt", 2, 30);
// 遇到warn或者更高级别,比如err,critical 立即flush日志,防止丢失
logger->flush_on(spdlog::level::warn);

完整代码

// spdlog
#include "spdlog/spdlog.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include <iostream>
#include <memory>

// spd 带行号的打印,同时输出console和文件
#define DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_DEBUG(spdlog::get("daily_logger"), __VA_ARGS__)
#define LOG(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_INFO(spdlog::get("daily_logger"), __VA_ARGS__)
#define WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_WARN(spdlog::get("daily_logger"), __VA_ARGS__)
#define ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_ERROR(spdlog::get("daily_logger"), __VA_ARGS__)

int main(int argc, char *argv[]) {
    // 按文件大小
    //auto file_logger = spdlog::rotating_logger_mt("file_log", "log/log.log", 1024 * 1024 * 100, 3);
    // 每天2:30 am 新建一个日志文件
    auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
    // 遇到warn flush日志,防止丢失
    logger->flush_on(spdlog::level::warn);
    //每三秒刷新一次
    spdlog::flush_every(std::chrono::seconds(3));
    
    // Set the default logger to file logger
    auto console = spdlog::stdout_color_mt("console");
    spdlog::set_default_logger(console);
    spdlog::set_level(spdlog::level::debug); // Set global log level to debug

    // change log pattern
    // %s:文件名
    // %#:行号
    // %!:函数名
    spdlog::set_pattern("%Y-%m-%d %H:%M:%S [%l] [%t] - <%s>|<%#>|<%!>,%v");

    LOG("test info");
    ERROR("test error");
    
    // Release and close all loggers
    spdlog::drop_all();
}

控制台输出

/Users/xuyc/repo/sd_linux/cmake-build-debug/sd_linux
[2020-04-30 16:14:41.816] [console] [info] [main.cpp:608] test info
[2020-04-30 16:14:41.816] [console] [error] [main.cpp:609] test error

Process finished with exit code 0

文件
在这里插入图片描述

附录

网上说只需要头文件即可,不过我还是链接了。。。

CMakeList.txt

cmake_minimum_required(VERSION 3.15)
project(sd_linux)

set(CMAKE_CXX_STANDARD 14)
AUX_SOURCE_DIRECTORY(./ SRC_LIST)
AUX_SOURCE_DIRECTORY(./jsoncpp SRC_LIST)

// 包含spdlog的头文件
INCLUDE_DIRECTORIES(./jsoncpp ./spdlog/include)
// 包含spdlog的动态库目录
LINK_DIRECTORIES(./ ./spdlog/build)

add_executable(sd_linux ${SRC_LIST})

// 链接spdlog动态库
TARGET_LINK_LIBRARIES(sd_linux curl iconv spdlog)

关于

推荐下自己的开源IM,纯Golang编写:

CoffeeChat:
https://github.com/xmcy0011/CoffeeChat
opensource im with server(go) and client(flutter+swift)

参考了TeamTalk、瓜子IM等知名项目,包含服务端(go)和客户端(flutter),单聊和机器人(小微、图灵、思知)聊天功能已完成,目前正在研发群聊功能,欢迎对golang和跨平台开发flutter技术感兴趣的小伙伴Star加关注。

————————————————
版权声明:本文为CSDN博主「许非」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xmcy001122/article/details/105665732

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++日志库实战——spdlog,是不是感觉log4cxx有点笨重,不妨试一试spdlog 的相关文章

  • 使用 Log4J 记录 Spring bean 初始化

    当我运行我的应用程序时 它会在 bean 初始化时停止 但不显示任何日志条目 所以我不知道发生了什么 Log4j properties log4j rootLogger DEBUG stdout R log4j appender stdou
  • Logstash 与 log4j socketappender 不起作用

    我正在尝试通过 log4j 套接字附加程序流式传输我的日志 并尝试通过logstash log4j 输入插件检索相同的日志 我的logstash配置看起来像 input log4j type gt socketlogs port gt 19
  • -Dlog4j.formatMsgNoLookups=true 或 -Dlog4j2.formatMsgNoLookups=true - 哪个是正确的?

    哪一个是正确的 Dlog4j formatMsgNoLookups true Dlog4j2 formatMsgNoLookups true 或者两者都在工作 Ref log4j https dev to composite how to
  • 不同的应用程序写入相同的 log4j 日志文件

    我有 4 个 java Java EE 应用程序 其中两个是在 WebSphere 中运行的基于服务器的 j2ee 应用程序 另外两个是独立的 java 应用程序 我的日志框架是使用 log4j properties 的 log4j 问题
  • 清理 Tomcat 访问日志条目

    在我们的日志中 我们看到信用卡号码是由于人们使用 CC 信息点击我们应用程序中的一些 ULR 我不知道他们为什么这样做 我们希望清理这些信息 出于 PCI 考虑 甚至不将其保存到磁盘 因此 我希望能够在日志条目到达日志文件之前对其进行清理
  • 停止从依赖项向控制台显示记录器输出

    我的 Java 项目中有一些 Maven 依赖项 它们使控制台输出与冗余日志信息变得混乱 我想禁用此类日志记录 设置additivity财产给false可能有帮助 但无法正确使用它 我正在寻找一个log4j xml仅打印日志输出的配置 wa
  • 转换 LOG4J >> SLF4J + logback

    我目前的任务是将所有出现的 LOG4J 更改为 SLF4J 包括必要时的 logback 我已经设法将所有旧的 log4j xml 转换为 logback xml 并强制使用 logback 附加程序 但是 我刚刚发现代码中的一行还无法转换
  • Log4j2 模拟 Appender

    我有一堂课 其中我获取了所有属性 并在登录之前隐藏了它们的密码 Override public void afterPropertiesSet throws Exception Properties loadedProperties thi
  • 多模块 Maven 项目中的 log4j

    如何在多模块 Maven 项目中实现 log4j 我是否将 log4j properties 文件添加到每个子模块的 src main resources 目录中 如果是这样 我是否必须为每个文件附加器指定不同的输出文件 或者有没有一种方法
  • log4j 记录器消息不显示在 JBoss Web 应用程序上

    我使用 Jboss 6 和我的 static Logger logger Logger getLogger Foo class 什么也不显示 尝试将 log4 添加到我的项目中 将其删除 将 log4j 文件放在我的 main resour
  • 如何仅在 log4j 中记录警告

    在 Struts 2 应用程序中 我们使用 log4j 进行日志记录 我只想记录警告 但是当我尝试在 log4j properties 中使用时 log4j rootLogger warn stdout 它也打印错误和致命日志 我只想要警告
  • 将 System.out.println 记录到单个应用程序的日志文件

    我们在 tomcat 上有多个应用程序 它们使用 System out println 语句记录到 catalina out 有一个应用程序会创建大量日志语句 因此我想将这些应用程序输出记录到单独的日志文件中 我创建了一个 log4j xm
  • 记录多线程应用程序中的活动

    我有一个 Java 分层应用程序 它有一个从不同点调用的多线程数据访问层 对该层的一次调用可能会产生多个线程来并行化对数据库的请求 我正在寻找的是一个日志记录工具 它允许我定义由各种线程组成的 活动 因此 数据访问层中的相同方法应根据其调用
  • 用户主目录中的 log4j 日志文件

    我正在开发一个可以在 OSX 和 Windows 上运行的应用程序 我希望将日志写入用户主目录 对于 OSX 它将位于 Users Library Application Support MyApp log 目录下 而在 Windows 下
  • logback 支持 log4j 附加程序吗?

    为 log4j 创建的自定义 Appender 扩展 AppenderSkeleton 可以与 new 一起使用吗logback框架 我知道logback带有自己的一组类似于 log4j 的附加程序 但这是否可以重用现有的附加程序 如何 以
  • 在 Spark java 应用程序中使用 log4j2

    我正在尝试使用 log4j2我的 Spark 工作中的记录器 基本要求 log4j2 配置位于类路径之外 因此我需要明确指定其位置 当我直接在 IDE 中运行代码而不使用spark submit log4j2效果很好 但是 当我使用以下命令
  • Grails Log4J 未登录生产环境

    我有一个 Grails 1 3 7 应用程序 并尝试在配置中设置 log4j 以用于生产 log4j 设置在开发中很好 但我无法在生产中显示任何内容 我正在尝试制作一个滚动文件等 但我无法显示任何内容 我什至在 信息 级别进行了配置 这样我
  • 并发 log4j

    我有自己的日志引擎 它将日志写入带有阻塞队列的单独线程上 为了使用 标准软件 我正在考虑切换到 log4j 我不希望我的高并发软件因日志命令而变慢 这些日志命令在调用命令时将所有内容写入磁盘 log4j 可以用作垃圾箱吗 Log4j 是大多
  • 使用Log4j在日志中输出Spark应用程序id

    我有一个用于 Spark 应用程序的自定义 Log4j 文件 我想输出 Spark 应用程序 ID 以及消息和日期等其他属性 因此 JSON 字符串结构如下所示 name time date level thread message app
  • Spark 执行器 STDOUT 到 Kubernetes STDOUT

    我在 Spark Worker 中运行的 Spark 应用程序将执行程序日志输出到特定文件路径 worker home directory app xxxxxxxx 0 stdout I used log4j properties将日志从

随机推荐

  • 新生代接口测试神器ApiFox总结,你真的会用吗?

    目录 导读 前言 一 Python编程入门到精通 二 接口自动化项目实战 三 Web自动化项目实战 四 App自动化项目实战 五 一线大厂简历 六 测试开发DevOps体系 七 常用自动化测试工具 八 JMeter性能测试 九 总结 尾部小
  • linux启动生成文件,Linux重新生成启动引导文件

    1 重新生成grub2的配置文件 grub mkconfig o boot grub grub cfg 2 将grub2安装到硬盘引导扇区 grub install root directory dev sda 3 使用密码保护grub2
  • Unicode编码详解

    Unicode定义 Unicode 统一码 万国码 单一码 是计算机科学领域里的一项业界标准 包括字符集 编码方案等 Unicode 是为了解决传统的字符编码方案的局限而产生的 它为每种语言中的每个字符设定了统一并且唯一的二进制编码 以满足
  • Java svg图片转png图片

    Java svg图片转png图片 比较简单 主要使用batik包里的batik transcoder模块 网上的教程引的包太多了 只是转化的话 这个包就够了 你们引用的时候 记得查一下version 之前我引用的包太老了 项目就起不来了 p
  • Windows下端口号被占用排查方法

    1 WIN R CMD进入命令行 本示例端口号为8081 实操根据自己的端口号来 查找哪个进程号 PID 占用了本端口号 netstat ano findstr 8081 通过PID查到对应占用程序 tasklist findstr 142
  • IP:网际协议

    本文是为了记录学习过程中的知识点所写 用于对自己的理解做一个记录 4位版本 目前的版本号为4 因此IP也称为IPv4 4位首部长度 首部占32bit 4字节 的数目 4bit最大值为15 也就是说最多为480bit 即60字节 包括选项 也
  • Axios----web数据交互方式

    一 VUE生命周期 Created gt Vue 对象创建完成触发的函数 二 缩写 v bind 给属性赋值 缩写为 v on 事件绑定 缩写为 缩写 三 计算属性 computed中定义 以匿名函数形式实现数据的操作 计算 返回的值为计算
  • Docker容器数据卷详解

    文章目录 1 数据卷介绍 2 简单使用 3 MySQL容器建立数据卷同步数据 4 常用命令 5 具名挂载和匿名挂载 5 1 匿名挂载 5 2 具名挂载 6 Dockerfile中设置数据卷 7 容器数据卷 1 数据卷介绍 Docker将运用
  • 详解MOSFET详解MOSFET与IGBT的本质区别与IGBT的本质区别

    http www dzsc com data 2017 11 27 113799 html
  • mysql中if()函数使用

    在mysql中if 函数的用法类似于java中的三目表达式 其用处也比较多 具体语法如下 IF expr1 expr2 expr3 如果expr1的值为true 则返回expr2的值 如果expr1的值为false 则返回expr3的值 其
  • (十)蓝牙MAC地址

    BLE MAC地址分类 1 BLE设备可以使用公共地址和随机地址 至少使用其中一种 也可以有两种 地址的长度是6个字节 严格来说广播中不用包含地址 默认已经有了 2 公共地址 从IEEE购买 保证唯一性 3 随机静态地址 自己定义 上电初始
  • 计算机网络不完全整理(下)--春招实习

    HTTP 从输入url到显示主页的过程 参考 segmentfault com a 119000000 DNS解析 网址到ip地址的转换 TCP连接 HTTP协议使用TCP作为传输层协议 发送HTTP请求 服务器处理请求并返回HTTP报文
  • Flink Watermark分配策略

    Flink Watermark分配策略 WaterMark是Flink为了处理Event Time窗口计算提出的一种机制 本质上是一种时间戳 主要用来处理乱序数据或者延迟数据的 这里通常watermark机制结合window来实现 wate
  • Spring 单例 bean 的线程安全问题

    首先解释一下什么是单例 bean 单例的意思就是说在 Spring IoC 容器中只会存在一个 bean 的实例 无论一次调用还是多次调用 始终指向的都是同一个 bean 对象 用代码来解释单例 bean public class User
  • Cisco L2TP 配置实例

    1 在企业端配置L2TP ENT LNS config username cisco password 0 cisco ENT LNS config vpdn enable ENT LNS config vpdn group myl2tp
  • 创建小程序WePY项目过程报错指南

    笔者在第一次创建小程序 WePY 项目的时候 遇到了各种各样的问题 也在网上搜索了一番 终于也还是把 WePY 项目创建起来了 为了日后遇到问题更快的处理 笔者也把在创建过程的遇到的问题记录了下来 如下 1 在 WebStorm 中创建一个
  • 用Python实现的这五个小游戏,你真的学会了嘛?

    相关文件 源码分享 问题解答 关注小编 私信小编领取哟 当然别忘了一件三连哟 对了大家可以关注小编的公众号哟 有很多资源可以领取的哟 Python日志 游戏名称 五子棋 雷霆战机 贪吃蛇 坦克大战 俄罗斯方块 开发环境 Python版本 3
  • 区块链DAPP开发入门课程(PHP版)

    1 前言及环境部署 1 1 课程说明 为什么有这个课程 入门区块链开发已有些时日 走过的坑实在是太多了 对于像我这种从事互联网软件开发多事的老兵来说 上手都有些吃力 可想而知对于新手来说就更难了 尤其是完全靠自学又没有人指导的情况 可能一个
  • navicat导入sql文件_中级数据分析-SQL入门

    一 如何快速学会SQL 黄金圈原则 1 为什么 目的 很多公司数据存放在数据库当中 SQL是操作数据库的语言 所以目前SQL是数据分析岗位几乎必备的技能 也是面试当中必须考察的能力 2 如何做 方法 入门 什么是数据库 sql 表和数据的新
  • c++日志库实战——spdlog,是不是感觉log4cxx有点笨重,不妨试一试spdlog

    c 日志库实战 spdlog 是不是感觉log4cxx有点笨重 不妨试一试spdlog 背景 更新记录 spdlog是什么 spdlog快速入门 编译 CMake手动方式 Vcpkg全自动方式 推荐 原生用法 实战代码 SpdlogWarp