![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
GO
Yuan_sr
这个作者很懒,什么都没留下…
展开
-
kubernetes中定时任务的实现
在上面的示例中,f是要运行的函数,period是周期时间,jitterFactor是抖动因子,sliding是一个布尔值,表示周期是否在运行f之后立即开始下一次定时器。JitterUntil函数是一个循环函数,它会在每个周期内运行一个函数f。当stopCh关闭时,循环将停止。这个函数是 Until 的语法糖,Until 函数的作用是在一定时间内重复调用函数 f,直到函数 f 返回 true 或者时间到期。Until函数是wait包中的一个函数,它可以用于在指定的时间间隔内重复执行函数,直到停止通道被关闭。原创 2023-06-26 15:49:35 · 1360 阅读 · 0 评论 -
golang容易导致内存泄漏的几种情况
golang 内存泄漏原创 2022-09-11 15:15:33 · 3407 阅读 · 2 评论 -
如何优化Golang中重复的错误处理
在看《Go入门指南》的一种用闭包处理错误的模式时,里面提到了一种错误的优雅处理方式,减少我们重复写if err:=f(); err != nil{}式的代码,感觉很心动,做了下测试,结论如下:能减少if err式的代码,代码可以变清新整洁。使用存在限制:只有当错误需要结束调用时才可以使用这种方法,如果被调用函数返回错误,但调用者函数需处理错误后,向下继续执行,则不能采用这种方法。 经常的写法 我们在设计函数时,错误处理要遵循以下2个规则: 被调用函数如果有错误,需要传递给调用者,一定要返回调用者收到转载 2021-11-10 16:40:58 · 600 阅读 · 0 评论 -
反射(reflect)机制
什么是反射官方对此有个非常简明的介绍,两句话耐人寻味:反射提供一种让程序检查自身结构的能力反射是困惑的源泉要深刻理解反射,个人感觉需要花时间在官方博客上再加以练习,循序渐进,慢慢体会。反射的三个定律反射就是检查interface的(value, type)对的,因为任何类型的变量或方法都是实现了空接口。具体一点说就是Go提供一组方法提取interface的value,提供另一组方法提取interface的type.官方提供了三条定律来说明反射,比较清晰,下面也按照这三定律来总结。反射包里原创 2021-08-06 16:28:37 · 292 阅读 · 0 评论 -
并发安全Context包的使用
前言–为什么需要ContextGolang context是Golang应用开发常用的并发控制技术,它与WaitGroup最大的不同点是context对于派生goroutine有更强的控制力,它可以控制多级的goroutine。context翻译成中文是”上下文”,即它可以控制一组呈树状结构的goroutine,每个goroutine拥有相同的上下文。典型的使用场景如下图所示:当一个请求被取消或超时时,所有用来处理该请求的 goroutine 都应该迅速退出,然后系统才能释放这些 goroutin原创 2021-08-03 16:27:16 · 300 阅读 · 0 评论 -
并发安全Sync包的使用
有时候在Go代码中可能会存在多个goroutine同时操作一个资源(临界区),这种情况会发生竞态问题(数据竞态)。Sync包主要实现了并发任务同步WaitGroup的几种方法和并发安全的互斥锁和读写锁方法,还实现了比较特殊的两个方法,一个是保持只执行一次的Once方法和线程安全的Map。sync.WaitGroup(同步等待)sync.WaitGroup内部维护着一个计数器Add(),计数器的值可以增加和减少。例如当我们启动了N 个并发任务时,就将计数器值增加N。每个任务完成时通过调用Done()方法原创 2021-08-03 16:22:49 · 255 阅读 · 0 评论 -
定时器Timer和Ticker
TimerTimer是一个定时器,代表未来的一个单一事件,通过Timer本身提供的管道将事件传递出去,言外之意是只执行一次。Timer的数据结构如下:type Timer struct { C <-chan Time r runtimeTimer}package mainimport ( "fmt" "time")func main() { // 1.timer基本使用 timer1 := time.NewTimer(2 * time.Second) t1 := t原创 2021-08-03 16:20:06 · 905 阅读 · 0 评论 -
Select多路复用
在某些场景下我们需要同时从多个通道接收数据。通道在接收数据时,如果没有数据可以接收将会发生阻塞,而select就可以同时监听一个或多个channel,直到其中一个channel准备好。select的使用类似于switch语句,它有一系列case分支和一个默认的分支。每个case会对应一个通道的通信(接收或发送)过程。select会一直等待,直到某个case的通信操作完成时,就会执行case分支对应的语句。具体格式如下: select { case <-chan1: //原创 2021-08-03 16:16:34 · 488 阅读 · 0 评论 -
Goroutine池
goroutine池的应用本质上是生产者消费者模型可以有效控制goroutine数量,防止暴涨需求:计算一个数字的各个位数之和,例如数字123,结果为1+2+3=6随机生成数字进行计算控制台输出结果如下:job id: 164362 random: 3002688297310473558 result: 81job id: 164363 random: 8188014692039052954 result: 84job id: 164364 random: 91995149531原创 2021-08-02 17:06:22 · 224 阅读 · 0 评论 -
Channel
为什么要用channel?单纯地将函数并发执行是没有意义的。函数与函数间需要交换数据才能体现并发执行函数的意义。虽然可以使用共享内存进行数据交换,但是共享内存在不同的goroutine中容易发生竞态问题。为了保证数据交换的正确性,必须使用互斥量对内存进行加锁,这种做法势必造成性能问题。Go语言的并发模型是CSP(Communicating Sequential Processes),提倡通过通信共享内存而不是通过共享内存而实现通信。如果说goroutine是Go程序并发的执行体,channel就是它原创 2021-08-02 17:02:52 · 194 阅读 · 0 评论 -
Goroutine
什么是GoroutineGoroutine的概念类似于线程,但 goroutine是由Go的运行时(runtime)调度和管理的。Go程序会智能地将 goroutine 中的任务合理地分配给每个CPU。Go语言之所以被称为现代化的编程语言,就是因为它在语言层面已经内置了调度和上下文切换的机制。在Go语言编程中你不需要去自己写进程、线程、协程,你的技能包里只有一个技能–goroutine,当你需要让某个任务并发执行的时候,你只需要把这个任务包装成一个函数,开启一个goroutine去执行这个函数就可以了原创 2021-08-02 16:58:49 · 203 阅读 · 0 评论 -
设计模式--适配器(Adapter)模式
模式定义将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作类图应用场景1.当你希望使用某些现有类,但其接口与你的其他代码不兼容时;2.当你希望重用几个现有的子类,这些子类缺少一些不能添加到父类中的公共功能时;优点1.符合单一职责原则;2.符合开闭原则要点总结Adapter模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用、类库迁移等方面非常有用GoF 23定义了两种Adapter模式原创 2021-07-27 00:14:45 · 100 阅读 · 0 评论 -
设计模式--代理(Proxy)模式
模式定义为其他对象提供一种代理以控制(隔离,使用接口)对这个对象的访问类图要点总结“增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方法,在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做proxyPorxy并不一定要求保持接口完整的一致性,只要能够实现间接控制原创 2021-07-27 00:05:18 · 225 阅读 · 0 评论 -
设计模式--解析器(Interpreter)模式
模式定义给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子类图要点总结Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的结构不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式使用interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模原创 2021-07-26 23:55:48 · 209 阅读 · 0 评论 -
设计模式--访问器(Visitor)模式
模式定义表示一个作用于某对象结构中的各元素的操作,使得可以在不改变(稳定)各元素的类的前提下定义(扩展)作用于这些元素的新操作(变化)类图要点总结Visitor模式通过所谓双重分发(double dispatch)来实现在不更改(不添加新的操作-编译时)Element类层次结构的前提下,在运行时透明地为类层次结构上的各个类动态添加新的操作(支持变化)所谓双重分发即Visitor模式中间包括了两个多态分发:第一个为accept方法的多态辨析,第二个为visitElementX方法的多态辨析Vi原创 2021-07-26 23:53:47 · 219 阅读 · 0 评论 -
设计模式--命令(Command)模式
模式定义将一个请求(行为)封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作类图要点总结Command模式的根本目的在于将“行为请求者”与“行为实现者”解耦,在面向对象语言中,常见的实现手段是“将行为抽象为对象”实现Command接口的具体命令对象ConcreteCommand有时候根据需要可能会保存一些额外的状态信息,通过使用Composite模式,可以将多个“命令”封装为一个“复合命令”MacroCommandGo语言代码实现工程目原创 2021-07-26 23:51:43 · 240 阅读 · 0 评论 -
设计模式--责任链(Responsibility_Chain)模式
模式定义使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间耦合关系,将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止类图要点总结Chain of Responsibility模式的应用场合在于“一个请求可能有多个接受者,但是最后真正的接受者只有一个”,这时候请求发送者与接受者的耦合有可能出现“变化脆弱”的症状,职责链的目的就是将二者解耦,从而更好地应对变化应用了Chain of Responsibility模式后,对象的职责分配将更具灵活性,我们可以在运行时动态添原创 2021-07-26 23:49:35 · 175 阅读 · 0 评论 -
设计模式--迭代器(Iterator)模式
模式定义提供一中方法顺序访问一个聚合对象中的各个元素,而又不暴露(稳定)该对象的内部表示类图要点总结迭代抽象:访问一个聚合对象的内部而无需暴露它的内部表示迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题Go语言代码实现工程目录iterator.gopackage Iteratortype Iterator interface { Index() int原创 2021-07-26 23:46:47 · 85 阅读 · 0 评论 -
设计模式--组合(Component)模式
模式定义将对象组合成树形结构以表示“部分–整体”的层次结构,Composite使得用户对单个对象和组合对象的使用具有一致性(稳定)类图要点总结Composite模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”的关系,使得客户代码可以一致地(复用)处理对象和对象容器,无需关系处理的是单个的对象,还是组合的对象容器将“客户代码与复杂的对象容器结构”解耦是Composite的核心思想解耦之后,客户代码将于纯粹的抽象接口–而给对象容器的内部实现结构–发生依赖,从而更能“原创 2021-07-26 23:44:23 · 280 阅读 · 0 评论 -
设计模式--备忘录(Memento)模式
模式定义在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到原先保存的状态类图要点总结备忘录(Memento)存储原发器(Originator)对象的内部状态,在需要时恢复原发器状态Memento模式的核心是信息隐藏,即Originator需要向外界隐藏信息,保持其封装性,但同时又需要将状态保持到外界(Memento)Go语言代码实现工程目录memento.gopackage Mementotype Memento struc原创 2021-07-26 23:41:57 · 94 阅读 · 0 评论 -
设计模式--状态(State)模式
模式定义允许一个对象在其内部状态改变时改变它的行为,从而使对象看起来似乎修改了其行为类图要点总结State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象,但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转化是原子性的–即要么彻底转化过来,要么不转换如果State对象没有实例变量,那么各个上下文可以共享一个State对象,从而节省原创 2021-07-26 23:39:23 · 173 阅读 · 0 评论 -
设计模式--享元(Flyweight)模式
模式定义运用共享技术有效地支持大量细粒度的对象类图应用场景如果系统有大量类似的对象,可以使用享元模式优点如果系统有大量类似的对象,可以节省大量的内存及CPU资源要点总结要点总结如果系统有解耦实现对象的代价问题,Flyweight主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理对象的数量太大从而导致对象内存开销加大–什么样的数量才算大?这需原创 2021-07-22 00:34:34 · 78 阅读 · 0 评论 -
设计模式--单例(Singleton)模式
模式定义指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象类图应用场景当代码不应该依赖于需要复制的对象的具体类时优点1.以不耦合具体类的情况下克隆对象;2.避免重复的初始化代码;3.更方便的构建复杂对象;要点总结Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”Prototype模式对于“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”的原创 2021-07-21 21:51:59 · 126 阅读 · 1 评论 -
设计模式--工厂方法(Factory Method)模式
模式定义定义一个用于创建对象的接口,让子类决定实例化哪一个类,使得一个类的实例化延迟到子类类图应用场景1.当你不知道该使用对象的确切类型的时候;2.当你希望为库或框架提供扩展其内部组件的方法时。主要优点1.将具体产品和创建者解耦;2.符合单一职责原则;3.符合开闭原则。要点总结Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱Factory Method模式通过面向对象的手法,将所要创建原创 2021-07-19 23:06:30 · 128 阅读 · 0 评论 -
设计模式--建造者(Builder)模式
模式定义将一个复杂对象的创建与他的表示分离,使得同样的构建过程可以创建不同的表示类图应用场景1.需要生成的对象具有复杂的内部结构;2.需要生成的对象内部属性本身相互依赖;3.与不可变对象配合使用;优点1.建造者独立,易扩展;2.便于控制细节风险;要点总结Builder模式主要用于“分步骤构建一个复杂的对象”,在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化变化点在哪里,封装哪里----Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动,其缺点在于难原创 2021-07-21 21:55:09 · 96 阅读 · 1 评论 -
设计模式--模板方法(Template Method)模式
模式定义定义一个操作的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法某些特定步骤类图要点总结Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用(像C++中虚函数的多态性)除了可以灵活应对子步骤的变化外,“不要调用我,让我来调用你”的反向控制结构是Template Method的典型应用Go语言代码实现工程目录template.go package Template 原创 2021-07-19 22:22:40 · 103 阅读 · 1 评论 -
设计模式--策略(Strategy)模式
模式定义定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化),该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)类图要点总结Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行交换Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是解耦合。含有许多条件判断语句的代码通常都需要Strategy模式如果Strategy对象没有实例变量,那么各个上下文可以共享一个Strategy原创 2021-07-19 22:33:02 · 101 阅读 · 1 评论 -
设计模式--桥(Bridge)模式
模式定义将抽象部分(业务功能)与实现部分(平台实现)分离,使它们都可以独立地变化。类图应用场景在业务功能具有抽象功能和差异实现时需要独立的适应后面可能遇到的变化时使用桥接模式优点1.符合开闭原则2.提供方法但是隐藏底层具体实现3.将功能和实现分离开来,有利于解耦要点总结Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化,所谓抽象和实现沿着各自维度的变化,即“子类化”它们Bridge模式有时候类似于多继承方案,但是多继承原创 2021-07-19 22:49:10 · 165 阅读 · 0 评论 -
设计模式--抽象工厂(Abstract Factory)模式
模式定义提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类类图应用场景程序需要处理不同系列的相关产品,但是你不希望它依赖于这些产品的具体类时可以使用抽象工厂模式优点1.可以确信你从工厂得到的产品彼此是兼容的;2.可以避免具体产品和客户端代码之间的紧密耦合;3.符合单一职责原则;4.符合开闭原则要点总结如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂完全可以“系列对象”指的是在某一特定系列下的对象之间原创 2021-07-19 23:08:53 · 83 阅读 · 0 评论 -
设计模式--原型(Prototype)模式
模式定义指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象类图应用场景当代码不应该依赖于需要复制的对象的具体类时优点1.以不耦合具体类的情况下克隆对象;2.避免重复的初始化代码;3.更方便的构建复杂对象;要点总结Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”Prototype模式对于“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”的原创 2021-07-22 00:31:41 · 85 阅读 · 1 评论 -
设计模式--观察者(Observer)模式
模式定义定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者都会收到通知并更新类图应用场景当更改一个对象的状态可能需要更改其他对象,并且实际的对象事先未知或动态更改时,使用观察者模式优点1.符合开闭原则2.可以在运行时建立对象之间的关系要点总结使用面向对象的抽象,Observe模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达到松耦合目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播观察者自原创 2021-07-19 22:37:30 · 169 阅读 · 0 评论 -
设计模式--门面(Facade)模式
模式定义为子系统中的一组接口提供一个一致(稳定)的界面,Facade模式定义了一个高层接口,这个接口使得这个子系统更加容易使用(复用)类图应用场景1.当你需要使用复杂子系统的有限但直接的接口时,请使用Facade模式2.当你需要将子系统组织成层时,请使用Facade模式优点简化客户端的调用要点总结要点总结从客户程序的角度来看,Facade模式简化了整个组件系统的接口,对于组件内部与外部客户程序来说,达到了一种“解耦”的效果–内部子系统的任何变化不会影响到facade接口的变化Fac原创 2021-07-22 00:37:49 · 123 阅读 · 0 评论 -
设计模式--中介者(Mediator)模式
模式定义用一个中介对象来封装(封装变化)一系列的对象交互,中介者使各对象不需要显示的相互引用,从而使其耦合松散(管理变化),而且可以独立地改变它们之间的交互类图应用场景当多个对象互相关联交互并存在复杂的引用关系时,且对新需求需要进行大量更改时使用中介者模式解耦合优点可以避免相互交互的对象之间的紧耦合引用关系,从而更好地抵御变化要点总结要点总结将多个对象间复杂的关联关系解耦,Mediator模式将多个对象间的控制逻辑进行集中管理,变“多个对象互相关联”为“多个对象和一个中介者关联”,简化原创 2021-07-22 00:46:37 · 376 阅读 · 1 评论 -
设计模式--装饰者(Decorator)模式
模式定义动态(组合)地给一个对象增加一些额外的职责,就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码并且减少子类个数)类图应用场景扩展一个类的功能或给一个类添加附加职责优点1.符合开闭原则2.不改变原有对象的情况下给一个对象扩展功能3.使用不同的组合可以实现不同的效果要点总结通过采用组合而非继承的手法,Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”Decor原创 2021-07-19 22:43:23 · 102 阅读 · 0 评论 -
消息队列--RabbitMQ简单使用
安装使用地址:http://www.rabbitmq.com/需要根据不同的版本选择不同的erlang安装erlang安装RabbitMQ首先需要安装erlang环境,根据GitHub上erlang中README配置yum源将上面的内容写入红线标注的文件中保存退出,然后安装erlangyum update -yyum install -y erlang-23.3.4安装RabbitMQ下载完成RabbitMQ的安装包后执行下面的命令安装yum install rabbitmq-原创 2021-07-14 23:33:17 · 147 阅读 · 1 评论 -
HTTP中通过get方法下载文件
http下载文件的本质就是在响应体中拿到响应数据并写入到文件的操作,第二种方式是实现了一个实时显示下载进度的功能package mainimport ( "fmt" "io" "net/http" "os")func downloadFile(url, fileName string) { resp, err := http.Get(url) if err != nil { panic(err) } defer func() {_ =原创 2021-07-08 00:04:22 · 4240 阅读 · 0 评论 -
HTTP中post方法提交不同格式的数据
http提交数据主要通过post方法实现,在提交不同格式的数据时最大的不同点在于数据的组织形式不同,同时需要设置不同格式对应的Content-type格式package mainimport ( "bytes" "encoding/json" "fmt" "io" "io/ioutil" "mime/multipart" "net/http" "net/url" "os" "strings")func postForm(){ da原创 2021-07-08 00:03:03 · 245 阅读 · 0 评论 -
HTTP中response响应数据获取
http的响应数据是封装在response中的,如果需要获取响应的具体内容我们可以通过下面的方法简单获取到package mainimport ( "fmt" "io/ioutil" "net/http")func responseBody(r *http.Response){ content, _ := ioutil.ReadAll(r.Body) fmt.Printf("%s", content) //{ // "args": {}, // "原创 2021-07-08 00:01:56 · 9417 阅读 · 0 评论 -
HTTP中request请求参数的设置
在发送的http请求中我们可以定制自己的请求体,下面是几个示例代码package mainimport ( "fmt" "io/ioutil" "net/http" "net/url")func printBody(r *http.Response){ content, err := ioutil.ReadAll(r.Body) if err != nil { panic(err) } fmt.Printf("%s", content)原创 2021-07-08 00:00:15 · 5291 阅读 · 0 评论 -
HTTP的四种请求方法
golang中net/http包提供了http相关操作的封装,其中get方法和post方法进行的进一步的封装,使用起来更加方便,其他的请求方式需要我们自己调用底层实现package mainimport ( "fmt" "io/ioutil" "net/http")func get(){ resp, err := http.Get("http://httpbin.org/get") if err != nil { panic(err) } d原创 2021-07-07 23:58:26 · 545 阅读 · 0 评论