golang中的单向channel和nil值channel

在阅读client-go代码时发现源码对channel的部分使用方式不太理解,一个是单项channel的使用,一个是nil值channel的使用,于是搜索总结一下。 在golang中可以定义channel为双向的,也可以将channel定义为只能接收或只能发送类型的,如下面所示: // You can edit this code! // Click here and start typing. package main func main() { // 普通双向的 var normalCh chan interface{} // 只能发送 var sendOnlyCh chan<- interface{} // 只能接收 var receiveOnlyCh <-chan interface{} <-sendOnlyCh receiveOnlyCh <- 1 } 编译上述代码,将会得到下列错误: ./prog.go:12:2: invalid operation: <-sendOnlyCh (receive from send-only type chan<- interface {}) ./prog.go:13:16: invalid operation: receiveOnlyCh <- 1 (send to receive-only type <-chan interface {}) Go build failed.…

eBPF技术介绍

最近在看cilium和calico关于eBPF功能,发现有许多不理解的地方,比如概念原理等,因此花费了一定的时间进行了学习和整理,翻了不少文档和博客,最后发现还是cilium社区的这篇文章讲解的最通透,希望后来人可以静下心来把这篇文章慢慢读下来并理解。开始方向错了,其实主要两条线,一个是基于llvm的c语言编写eBPF程序,涉及到一些宏,段定义,maps定义,btf等,llvm按照一定规范为我们编译和生成elf格式的文件,另一个是iproute2/bpftool等加载器将eBPF程序加载到内核,加载工具会读取elf中的各种段信息,将其加载到内核中,此处也会涉及段名称的约定,加载工具与编译器对于btf之间的约定。明白这两块之后再看内核提供的相关辅助函数和不同的map就可以做一些特定功能的bpf程序开发了。 简介 BPF(Berkeley Packet Filter ),中文翻译为伯克利包过滤器,是类 Unix 系统上数据链路层的一种原始接口,提供原始链路层封包的收发。1992 年,Steven McCanne 和 Van Jacobson 写了一篇名为《BSD数据包过滤:一种新的用户级包捕获架构》的论文。在文中,作者描述了他们如何在 Unix 内核实现网络数据包过滤,这种新的技术比当时最先进的数据包过滤技术快 20 倍。BPF 在数据包过滤上引入了两大革新: 一个新的虚拟机 (VM) 设计,可以有效地工作在基于寄存器结构的 CPU 之上; 应用程序使用缓存只复制与过滤数据包相关的数据,不会复制数据包的所有信息。这样可以最大程度地减少BPF 处理的数据; 由于这些巨大的改进,所有的 Unix 系统都选择采用 BPF 作为网络数据包过滤技术,直到今天,许多 Unix 内核的派生系统中(包括 Linux 内核)仍使用该实现。 2014 年初,Alexei Starovoitov 实现了 eBPF(extended Berkeley Packet Filter)。经过重新设计,eBPF 演进为一个通用执行引擎,可基于此开发性能分析工具、网络数据包过滤、系统调用过滤,系统观测和分析等诸多场景。eBPF 最早出现在 3.18 内核中,此后原来的 BPF 就被称为经典 BPF,缩写 cBPF(classic BPF),cBPF 现在已经基本废弃。现在,Linux 内核只运行 eBPF,内核会将加载的 cBPF 字节码透明地转换成 eBPF 再执行。 eBPF 新的设计针对现代硬件进行了优化,所以 eBPF 生成的指令集比旧的 BPF 解释器生成的机器码执行得更快。扩展版本也增加了虚拟机中的寄存器数量,将原有的 2 个 32 位寄存器增加到 10…

《C++注解》第9章 类和内存分配

第9章 类和内存分配 和C语言中的内存分配函数(如malloc)对比,C++中的内存分配是由new运算符完成的。malloc和new的主要区别如下: malloc自身不清楚被分配的内存将作何用。例如,当为int类型分配内存时,编程者必须提供一个正确的表达式,用于表示分配多少个sizeof(int)大小的空间。相比之下,new只需指定一个类型就可,编译器会隐式调用sizeof运算符。使用new是类型安全的。 ~~malloc分配的内存会被calloc舒适化为指定的值~~(译者注:malloc不会调用calloc初始化,malloc分配的内存是未被初始化的,calloc分配的内存会被自动初始化为0)。如果分配的内存是为一个对象使用,这是不必要的。因为new运算符会根据该对象的构造函数对该内存进行特定的初始化。 采用C中的内存分配函数,我们必须要检查这些函数的返回值是否为NULL,采用new分配内存时则不需要这样的检查,我们可以通过配置new_handler来指定new失败时要执行的动作。 free和delete的比较:delete运算符能够保证在回收某个对象的内存时,这个对象的析构函数会被调用。 本章重点要讲的就是创建对象和销毁对象时,构造函数和析构函数的自动执行。在C程序的开发中,许多问题都是由不正常的内存分配和内存泄露造成的,如内存未被分配,内存未被释放,内存未被初始化,内存访问越界等。虽然C++不能自动的解决这些问题,但它给我们提供了有用的工具来防止这类问题的发生。 在C中,malloc经常用来处理字符串。在string.h其中有一些字符串处理函数是基于malloc的,如strdup。这些函数在C++中,我们应避免使用这些函数,取而代之,我们应该使用string类以及new和delete运算符。 Memory allocation procedures influence the way classes dynamically allocating their own memory should be designed. 因此,除了new和delete运算符,本章还会讨论这些内容。首先,先介绍new和delete运算符,然后会讨论: 析构函数:在对象被销毁时被调用的成员函数。 赋值运算符:允许我们将一个对象赋值给同类的另一个对象。 this指针:在一个对象的成员函数被调用时,明确的引用这个对象。 拷贝构造:创建一个对象副本的构造函数。 移动构造:从一个匿名的临时变量穿件对象的构造函数。 9.1 new和delete运算符 C++定义了两个用来分配和释放内存的运算符,分别为new和delete。 下面是一个简单的示例程序来演示如何使用他们。一个int类型的指针指向new申请的内存,之后该内存通过delete进行释放。 int *ip = new int; delete ip; 下面是new和delete运算符的一些特性: new和delete是运算符,因此使用时不需要加括号 new返回指向一个内存区域,该指针的类型为被分配内存的对象类型(上例中,返回一个int类型的指针) new后面跟着一个类型名称作为操作数,因此能为该类新的对象分配正确数量的内存 new是一个类型安全的操作符,它总是能够返回一个指向和操作数相同类型对象的指针,并且该指针的类型和这个对象的类型相同 new可能会失败,但是开发者不必担心这个问题,程序中不需要像使用malloc时那样必须检测内存是否分配成功,在9.2.2中会深入讨论new的这个特性 delete返回void new和delete必须成对使用,一个由new申请的内存,最终要有一个相对应的delete执行,以免内存泄露的情况发生 delete能够安全的处理0指针(什么也不做) delete只能释放由new申请的内存,不应该用来释放使用malloc申请的内存 C++中,malloc和相近的内存分配函数(如calloc)是被弃用的,因此我们应避免使用它们 new运算符既可以为基本类型分配内存,又可以给对象分配内存。当为基本类型或者没有构造函数的struct类型分配内存时,不能保证这些内存被初始化为0,但是我们可以为其提供一个初始化表达式。 int *v1 = new int; // not guaranteed to be initialized to 0 int *v1 = new…

python多个装饰器的先后顺序

当一个函数被多个装饰器装饰时,会从离函数最近的装饰器开始对函数进行装饰,离函数最远的装饰器最后装饰,越近的装饰器会在最终的函数的内层,越远的越会在函数的外层,所以最外层装饰器中的代码最先执行,最内层的装饰器的代码最后执行。 #!/usr/bin/env python3 def dec1(f): print("dec1, before") def dec(): print("dec1") f() return dec def dec2(f): print("dec2, before") def dec(): print("dec2") f() return dec def dec3(f): print("dec3, before") def dec(): print("dec3") f() return dec @dec3 @dec1 @dec2 def printf(): print("real function") printf() 这段代码将会输出 dec2, before dec1, before dec3, before dec3 dec1 dec2 real function…

python中类与类型的统一是指什么

世间具有共同特性的东西,我们可以将其归为一类,为它起个名字,叫吃的,喝的。。。但他们并不是具体的事物,而是抽象的名词。python中的类型(type)和对象(object)同样是抽象名词,type用来描述object具有哪些共同的属性,比如说苹果(object),香蕉(object),他们都能吃,可以把他们归为”吃的”类(type),能吃是它们的一个属性,当然他们还有其他属性,也可根据其他属性归类。 python中的每个object都具有一个class属性,他的值是一个type类型的实例,是一个实际对象,这个实力描述了这个类型的名称,属性和有哪些方法,比如说怎么吃,包皮吃还是直接吃。一只猪和一只狗是两个实际的object,它们是动物,那就让他们的class指向动物类型(type)的一个实例。每个type实例都有一个base属性,这是指继承于上一级的属性,比如动物和人,人是动物的一个子类,动物都有吃的属性,但人具有说话的属性。对于动物和人有两个类(type),animal和human,在ainimal中有吃的属性,在human中有说话的属性,当实例化一个human时,我们要调用吃的方法,会在human中定义查找这个方法,没有找到,那么就看看human.base中有哪些类,找到了动物,在animal的定义中找到了吃的属性,那么就调用这个属性。 值得我们记住的就是在python中所有的东西都是对象,他们都继承自object,既然都是对象,那么他们就都具有type属性(class)。object也不例外,它的class就是type。如果object是一头猪,那么class可能就是一个type的实例————动物。type也是一个对象,它的class就是type。 其实可以这样简单理解,我们所定义类型(class)或系统内建的类型(class)都是type的实例,我们用到的实例化后得到的东西是type的实例的实例,并且这些class都继承于class object。 这是我的个人理解,如有不对之处欢迎指出。…

python中的类属性和实例属性

python中的实例属性指和每个实际实例相关的属性,当类A继承自B时,a = A()读取a.data,会首先在a.dict中查找data,也就是实例中查找data属性,dict其实就是存储实例属性的地方。当在a中查找到时(也就是在dict中),返回该指,如果data属性不在a中,那么会查找类及父类中的该属性。当对a.data赋值时,由于python动态绑定(或者其他原因),就直接在a的dict中赋值,比如append方法。 不管是类A,类B还是A的实例a或者B的实例b,在python眼中,它们都是实例,需要有位置存放与这些实例相关的数据,这正是dict的作用,此外除了dict外,在内部可能还会有个code属性,用来查找代码的位置等。另外,python看待类A和类B是完全一样的,它们都是同一个类型,继承关系只是规定了python在访问对象实例(python眼中的)的属性时,需要去哪里找而已。 以上是我个人观点,不代表正确,欢迎大家指正。…

PHP通过魔术方法实现多继承与重载

 PHP所提供的”重载”(overloading)是指动态地”创建”类属性和方法。我们是通过魔术方法(magic methods)来实现的。当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。本节后面将使用”不可访问属性”和”不可访问方法”来称呼这些未定义或不可见的类属性或方法。所有的重载方法都必须被声明为 public。 <?php class Parent1 { public function printFunction ($args) { echo 'parent1->printfunction ' . $args . '<br>'; } public function printFunction1 ($args) { echo 'parent1->printfunction1 ' . $args . '<br>'; } } class Parent2 { public function printFunction2 ($args) { echo 'parent2->printfunction2 ' . $args . '<br>'; } } class Child { protected $_parents = null; public function __construct($parents) { $this->_parents = $parents; } public function __call($method, $args)…