<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[fcopy的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/fcopy</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; fcopy]]></copyright><item><title><![CDATA[MIT6.5840 lab3A]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/146441863</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/146441863</guid><author>fcopy</author><pubDate>Sun, 23 Mar 2025 15:49:51 +0800</pubDate><description><![CDATA[const (CandidateLeadermu sync.Mutex // 加锁以保护对该节点状态的共享访问peers []*labrpc.ClientEnd // RPC端点persister *tester.Persister // 用于保存此节点已持久化状态的对象me int // 此节点在 peers 数组中的索引dead int32 // 由 Kill() 函数设置// 持久性状态currentTerm int // 记录当前的任期votedFor int // 投给了谁。]]></description><category></category></item><item><title><![CDATA[sylar：日志管理]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/144131201</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/144131201</guid><author>fcopy</author><pubDate>Mon, 16 Dec 2024 12:54:06 +0800</pubDate><description><![CDATA[宏是由 预处理器 在编译之前展开的，它通过文本替换来处理代码。宏通常使用 #define 来定义。性能：宏在编译前直接替换代码，因此 没有函数调用的开销。这在某些性能关键的代码中非常有用，比如需要大量重复计算的常量表达式。灵活性：宏可以接受任意复杂的参数，并通过字符串化 (#) 或拼接 (##) 来动态生成代码。调试困难：宏没有类型检查，它们在预处理阶段展开，调试时你无法看到宏展开后的结果。如果宏中存在错误，编译器可能会提示不明确的错误信息。]]></description><category></category></item><item><title><![CDATA[sylar高性能服务器框架：CMakeLists.txt文件解析]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/144215117</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/144215117</guid><author>fcopy</author><pubDate>Mon, 16 Dec 2024 12:53:20 +0800</pubDate><description><![CDATA[force_redefine_file_macro_for_sources(targetname) 这个 CMake 函数的主要目的是 重定义源文件中的 _ _ FILE _ _ 宏，使其包含相对于项目根目录的文件路径，而不是默认的绝对路径。是 CMake 中用来创建一个共享库（Shared Library）的命令，具体来说，它创建了一个名为 sylar 的共享库，并将源文件列表 LIB_SRC 中列出的文件编译成这个库。：是之前定义的 CMake 变量，代表最终需要编译成库的源文件列表。]]></description><category></category></item><item><title><![CDATA[Golang项目：实现生产者消费者模式]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/144051110</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/144051110</guid><author>fcopy</author><pubDate>Tue, 26 Nov 2024 17:00:40 +0800</pubDate><description><![CDATA[因为，如果我们没有先关闭控制channel，那么消费者和生产者就都还没有收到停止的消息，在两行语句的时间差中，会发生很多写入channel的操作。多对多模式，消费者和生产者都不主动退出，我们通过一个第三方信号来控制退出。同时创建one-one.go文件，来实现单生产者单消费者模型。如果先关闭数据channel，在关闭控制channel。Chanel的线程安全的，所以可以直接执行并发操作。报错，说我们往关闭了的channel里写数据。所以我们要先关闭控制channel。这时候我们关闭channel。]]></description><category></category></item><item><title><![CDATA[Golang项目：实现一个内存缓存系统]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143990877</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143990877</guid><author>fcopy</author><pubDate>Sun, 24 Nov 2024 16:28:39 +0800</pubDate><description><![CDATA[unsafe.Sizeof 来获取一个接口值（interface{}）的大小时，它实际上返回的是接口结构体本身的大小，而不是接口中存储的具体值的大小。现在的问题是，我们只是设置了，在过期之后，就不能访问了，但是实际上还占用着缓存，只有在再一次Get的时候，发现过期了，才会删除掉。使得我们的Set方法的time部分参数为可选择填写0-n个参数，但我们只使用第一个expire[0]作为我们使用的参数。我们在cache目录中，新建一个单元测试，memCache_test.go。如：get，add，del操作。]]></description><category></category></item><item><title><![CDATA[golang开源框架：命令行框架cobra]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143876894</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143876894</guid><author>fcopy</author><pubDate>Tue, 19 Nov 2024 17:20:48 +0800</pubDate><description><![CDATA[四个钩子函数执行顺序：PreRun --》Run --》接下来，我们来看继承import ("fmt"fmt.Println("钩子案例，run函数")},//run函数之前执行},//run函数之后执行},//	run之前},//run之后},fmt.Println("钩子案例，run函数")},//run函数之后执行},//run之后},可以看到，我们没有写PersistentPreRun（）和PostRun。]]></description><category></category></item><item><title><![CDATA[golang开源框架：go开源验证框架validator]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143852360</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143852360</guid><author>fcopy</author><pubDate>Mon, 18 Nov 2024 21:53:10 +0800</pubDate><description><![CDATA[当我们从map进入dive之后，就会发现有两个值key和value，可以先验证key再验证value。gte=5,lte=10，number ---- 是大于等于5小于等于10的数字。如果表示字符串，而是直接是数字，那么number和numeric就没有区别。对于数字类型的字符串，需要用numeric来校验（它可以校验小数点）中第一个满足了第一维度有3个，但是第二维度大于5个则都不满足。可以验证slice的长度，至于内容，看本文第三节。可以看到，第三个报错，OpCode只能是1或者2。]]></description><category></category></item><item><title><![CDATA[Golang云原生项目：—实现ping操作]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143831614</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143831614</guid><author>fcopy</author><pubDate>Sun, 17 Nov 2024 20:04:44 +0800</pubDate><description><![CDATA[记住，运行时需要以管理员身份，才能解析socket。测试显示，可以成功拿到命令行的参数。定义ICMP报文格式。]]></description><category></category></item><item><title><![CDATA[GOLANG笔记第四周]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143659365</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143659365</guid><author>fcopy</author><pubDate>Fri, 15 Nov 2024 13:09:48 +0800</pubDate><description><![CDATA[原本的本地函数放到另一个服务器上运行，但是引入了很多新问题Call 的id映射序列化和反序列化网络传输。]]></description><category></category></item><item><title><![CDATA[go debug日记：protoc -I . helloworld.proto --go_out=plugins=grpc:.错误debug]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143763517</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143763517</guid><author>fcopy</author><pubDate>Thu, 14 Nov 2024 12:18:47 +0800</pubDate><description><![CDATA[用来生成与 gRPC 相关的代码（例如 gRPC 服务的客户端和服务器代码）。path 表示生成的go文件的存放地址，会自动生成目录的。用来生成常规的 Go 代码（例如消息的 Go 结构体）。插件中，gRPC 相关的 Go 代码不再通过 –运行成功，生成helloworld.pb.go文件。即，没有指定生成的go文件位置，需要在文件中添加。使用protoc生成go的文件出现bug。name 表示生成的go文件所属的包名。]]></description><category></category></item><item><title><![CDATA[c++进阶（3）]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143382369</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143382369</guid><author>fcopy</author><pubDate>Fri, 01 Nov 2024 10:02:33 +0800</pubDate><description><![CDATA[提问：如果程序发生了不正常运行，比如在if语句内直接return了，那么就没有unlock操作，锁就直接废了。存在竞态条件：多线程程序执行的结果是一致的，不会随着cpu对线程不同的调度顺序，而产生不同的运行结果。t.detach（）：把t线程设置为分离线程，主线程结束，整个进程结束，所有子线程都自动结束了！std::thread定义一个线程对象，传入线程所需要的线程函数和参数。线程间的互斥=》mutex=》用lock_guard封装mutex。互斥锁是比较重的，如果临界区代码做的事情稍微的复杂，多。]]></description><category></category></item><item><title><![CDATA[c++进阶（2）]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143288418</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143288418</guid><author>fcopy</author><pubDate>Thu, 31 Oct 2024 10:05:07 +0800</pubDate><description><![CDATA[一：关键字和语法auto：可以根据右值，推到出右值的类型，然后左边变量的类型也就已知了。nullptr：指针专用，能和整数进行区别}//底层就是通过指针或迭代器来实现的右值引用：move移动语义函数和forward类型完美转发函数。模板的一个新特性：typename…A 表示可变参（类型参数）二：绑定器和函数对象bind绑定器function对象lambda表达式三：智能指针shared_ptr和weak_ptr四：容器unordered_set和unordered_map;]]></description><category></category></item><item><title><![CDATA[c++进阶（1）]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143232466</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143232466</guid><author>fcopy</author><pubDate>Mon, 28 Oct 2024 10:56:33 +0800</pubDate><description><![CDATA[原则一： 函数参数传递过程中，对象优先按引用传递，不要按值传递。可以省一个形参的构造和析构原则二：函数返回对象的时候，应该优先返回一个临时对象，而不要返回定义过的对象直接构造，不产生临时对象其次，我们虽然省去了在函数方法中创建临时对象，即从：函数方法中创建的对象=》main栈帧中创建临时对象用于传递=》传递给t2变成了：直接main栈帧中创建临时对象=》传递给t2但是其实还可以优化直接用构造方法构造t2int main()Test t1;]]></description><category></category></item><item><title><![CDATA[手写数据库连接池---C++11（下）]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143220812</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143220812</guid><author>fcopy</author><pubDate>Sat, 26 Oct 2024 13:37:33 +0800</pubDate><description><![CDATA[通过返回智能指针来控制连接的释放，当连接出作用域的时候，智能指针自动调用析构函数，此时只要修改析构函数，让他把资源归还给连接池，而不是删除就可以。当队头元素超时时，陆续释放超时资源，直到没有，或者已经到连接池初始大小。如果连接池空了，生产者就检查，此时连接数量是否超过了设置的最大连接数。---- ---- 如果在最大空闲时间内获取，检查到非空，则跳出循环。---- ---- 如果超时，获取连接失败，返回nullptr。在main函数中实现，添加1000条数据库数据，记录时间。]]></description><category></category></item><item><title><![CDATA[手写数据库连接池---C++11（上）]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143077505</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143077505</guid><author>fcopy</author><pubDate>Thu, 24 Oct 2024 22:03:00 +0800</pubDate><description><![CDATA[连接池事先会和MySQL Server创建initSize个数的connection连接。当应用发起MySQL访问时，不用再创建和MySQL Server新的连接，直接从连接池中获取一个可用的连接就可以。使用完成后，并不去释放connection，而是把当前connection再归还到连接池当中。当并发访问MySQL Server的请求增多时，初始连接量已经不够使用了，此时会根据新的请求数量去创建更多的连接给应用去使用。]]></description><category></category></item><item><title><![CDATA[施磊c++基础8]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143082401</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143082401</guid><author>fcopy</author><pubDate>Tue, 22 Oct 2024 16:52:20 +0800</pubDate><description><![CDATA[C++STL : standard template libaray底层数据结构：动态开辟的数组。每次以空间大的二倍扩容增加
vec.push_back(20); 末尾添加元素20 — O(1)
vec.insert(it，20);在it迭代器指向的位置插入元素20 — O(n)删除
vec.pop_back; 末尾删除元素 ---- O(1)
vec.erase(it) ;删除it迭代器指向的位置的元素 — O(n)查询
operator[ ]使用vec[ i ]访问第i个位置元素 — O(1)
iter]]></description><category></category></item><item><title><![CDATA[施磊c++基础7]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/143063467</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/143063467</guid><author>fcopy</author><pubDate>Sat, 19 Oct 2024 13:30:29 +0800</pubDate><description><![CDATA[注意：此时需要在D中加入A的构造，即使从继承类看，他并没有直接继承A。但是由于B,C都是虚继承，此时A的构造就要定位到D中对A进行构造；由于内存结构*p指向的是派生类基类部分数据的起始地址D8,但是vbptr和mb都还在前面，这时候delete p；这两句是一样的，只不过使用第二种，可以保证类型转换是安全的，如果要转换成不符合的类型就会报错。基类指针指向派生类对象，永远指向的是派生类基类部分数据的起始地址。对于第一种，int转char，编译器认为是安全的，就可以通过。d的内存布局 ---- 占20字节。]]></description><category></category></item><item><title><![CDATA[施磊c++基础6]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/142958391</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/142958391</guid><author>fcopy</author><pubDate>Fri, 18 Oct 2024 22:18:19 +0800</pubDate><description><![CDATA[当new Base()的时候，Base()的构造函数调用了clear(),把new的Base对象的内容全部归零了，包括vfptr，而在运行的时候，找不到vftable了，就出错了。如果派生类中的方法，和基类继承来的方法，返回值，函数名，参数列表都相同，而基类的方法是虚函数，那么这个派生类的方法，自动处理成虚函数。一个类里面定义了虚函数，那么这个类定义的对象，其运行时，内存中开始的部分，多存储一个vfptr虚函数指针，指向相应类型的虚函数表vftable。底层是通过动态绑定来实现的。]]></description><category></category></item><item><title><![CDATA[施磊c++基础5]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/142904632</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/142904632</guid><author>fcopy</author><pubDate>Tue, 15 Oct 2024 16:40:04 +0800</pubDate><description><![CDATA[示例代码1 — 删除容器中的偶数i < 20;++i)for (;it!报错了！！！为什么？//第一次调用erase以后，迭代器it就失效了//那么再进行++就报错示例代码2 — 给vec容器中所有的偶数添加一个小于偶数值1的数字for (;it!也会报错在遇到第一个偶数的时候，是把第一个偶数及其以后的迭代器全部失效所以到底为什么会失效？]]></description><category></category></item><item><title><![CDATA[施磊c++基础4]]></title><link>https://blog.youkuaiyun.com/fcopy/article/details/142886422</link><guid>https://blog.youkuaiyun.com/fcopy/article/details/142886422</guid><author>fcopy</author><pubDate>Sun, 13 Oct 2024 21:04:02 +0800</pubDate><description><![CDATA[当使用pop（）的时候，仅仅是_last–了，原来Test指向的内存并没有析构掉，当创建新对象时，原来的内存就丢掉了。,那么他就会强转为int类型，并且抛出一个警告，说明在T类型转换时可能会发生数据丢失。这使得我们可以只用一套代码实现一套逻辑，至于具体的实例化，交给编译器就行了。可以根据用户传入的实参类型，来推导出模板类型参数的具体类型。其实，在STL中，有很多的对于字符串类型的特例化版本。，a与b是同一类型，此时编译器无法判断，就会报错。模板函数，模板的特例化，非模板函数的重载关系。]]></description><category></category></item></channel></rss>