Content Disposition

Content-Disposition 常见是用在 http 请求的 Response 的 Header 头部. 告诉请求客户端(浏览器) 如何处理内容; Content-Disposition是在 MIME 标准定义的. http 中的用法只是其中的一小部分. 语法参数 inline 会在浏览器内部显示 1 Content-Disposition: inline attachment 会被保存成文件 1 Content-Disposition: attachment 后面可以跟 filename, 值为预设文件名称, 中间使用;分号隔开. 1 Content-Disposition: attachment; filename="filename.jpg" 拓展参数, 有两个文件名称参数可选 filename* filename filename* 采用了 RFC 5987 中规定的编码方式, 假如两个参数都使用 filename* 的优先级更高 RFC 5987 该提议最终还是引用 RFC 2231 中的编码方式. 下面简单介绍一下语法 *星号用于标记该同名参数是支持该编码语法的, 就如( filename* 之于 filename) '单个逗号用于分割 字符集名称 , 语言, 文件名称 %百分号用于标记编码方式, 参考RFC 2047, 所以文件名中不能有% 1 filename*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A 使用us-ascii编码, en-us英语 ...

<span title='2022-09-04 21:32:24 +0800 +0800'>September 4, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

我与地坛

概括 我为什么要读这本书? 我觉得生活挺无聊, 人生活着没有什么意义. 听说在这本书中会有人生的意义 这本书怎样影响了我? 看清楚自己之所以活着, 就如史铁生所说, 就是还想得到什么. 并不是如我嘴上所说的: “人生活着没什么意义” 打算更加大胆地去追求自己想要"得到"的东西 看清楚做某一件事情的意义 – 不只是看重结果, 也要去看重过程 书中的三句精华句子? 可我为什么还想活呢? 因为你还想得到点儿什么, 你觉得你还是可以得到点儿什么的, 比如说爱情, 比如说价值感之类的, 人真正的名字叫欲望 只要你最最关心的是目的而不是过程你无论怎样都得落入绝境,只要你仍然不从目的转向过程你就别想走出绝境。 世上有一种东西,其价值远远超过它的价格。这儿的价值,并不止于“物化劳动”,还物化着春天整整一个季节的能量。 上帝从来不对任何人施舍“最幸福”这三个字,他在所有人的欲望前面设下永恒的距离,公平地给每一个人以局限。 此岸永远是残缺的,否则彼岸就要坍塌。 三句话总结本书 尊重不完美, 不要抱怨, 不断地去追求完美 看清楚自己想要得到什么 人生不能只看重目的, 要去享受这个过程. 书摘 在满园弥漫的沉静光芒中,一个人更容易看到时间,并看见自己的身影。 树干上留着一只蝉蜕,寂寞如一间空屋;露水在草叶上滚动,聚集,压弯了草叶轰然坠地摔开万道金光。”“ 上帝在交给我们这件事实的时候,已经顺便保证了它的结果,所以死是一件不必急于求成的事,死是一个必然会降临的节日。 剩下的就是怎样活的问题了。这却不是在某一个瞬间就能完全想透的,不是能够一次性解决的事,怕是活多久就要想它多久了,就像是伴你终生的魔鬼或恋人。 看来差别永远是要有的。看来就只好接受苦难——人类的全部剧目需要它,存在的本身需要它。看来上帝又一次对了。 就命运而言,休论公道。 其实总共只有三个问题交替着来骚扰我,来陪伴我。第一个是要不要去死,第二个是为什么活,第三个,我干吗要写作。 人为什么活着?因为人想活着,说到底是这么回事,人真正的名字叫做:欲望。 可我为什么还想活呢?因为你还想得到点儿什么,你觉得你还是可以得到点儿什么的,比如说爱情,比如说价值感之类,人真正的名字叫欲望。 结果你又发表了几篇,并且出了一点儿小名,可这时你越来越感到恐慌。我忽然觉得自己活得像个人质,刚刚有点儿像个人了却又过了头, 人都忍不住要为生存找一些牢靠的理由。你不担心你会枯竭了?我不知道,不过我想,活着的问题在死前是完不了的。 就算是三个月!我平白地相信这样一个期限。 多年以后才听一位无名的哲人说过:危卧病榻,难有无神论者。 但在命运的混沌之点,人自然会忽略着科学,向虚暝之中寄托一份虔敬的祈盼。 机会不在外面在心里,结婚的机会有可能在外边,可爱情的机会只能在心里 那位台湾作家三毛说得对:爱如禅,不能说不能说,一说就错。 别人告诉我,她昏迷前的最后一句话是:“我那个有病的儿子和我那个还未成年的女儿……” 砌墙盖房,不单为避风雨,因为大家都有些秘密,其次当然还有一些钱财。秘密,不信你去慢慢推想,它是趣味的爹娘。 千万别把运动和能量,以及和时空分割开来理解。我随即得了启发:也千万别把人和意义分割开来理解。不是人有欲望,而是人即欲望。 如今想来,分明就是为了一个“轻”字:珍宝转眼被处理成垃圾,一段生命轻得飘散了,没有了,以为是什么原来什么也不是,轻易、简单、灰飞烟灭。一段生命之轻,威胁了生命全面之重,惶茫往灵魂里渗透:是不是生命的所有段落都会落此下场啊?人的根本恐惧就在这个“轻”字上,比如歧视和漠视,比如嘲笑,比如穷人手里作废的股票,比如失恋和死亡。轻,最是可怕。 艰苦的生活需要希望,鲜活的生命需要爱情,数不完的日子和数不完的心事,都要诉说。 也许是因为人缺了什么就更喜欢什么吧,我的两条腿一动不能动,却是个体育迷。 上帝从来不对任何人施舍“最幸福”这三个字,他在所有人的欲望前面设下永恒的距离,公平地给每一个人以局限。 我希望既有一个健美的躯体又有一个了悟人生意义的灵魂,我希望二者兼得。 难道我们不该对灵魂有了残疾的人,比对肢体有了残疾的人,给予更多的同情和爱吗? 既然是梦想不妨就让它完美些罢。何必连梦想也那么拘谨那么谦虚呢? 有知识不能只是有对物的知识,而是得有对人的了悟。 我们也完全可以把你以后的生活设计得无比顺利,但这样下去我们是不是绕了一圈又回到那不祥的阴影中去了?你将再没有企盼了吗?再没有新的追求了吗?那么你的心路是不是又在荒芜,于是你的幸福感又要老化、萎缩、枯竭了呢? 只要你最最关心的是目的而不是过程你无论怎样都得落入绝境,只要你仍然不从目的转向过程你就别想走出绝境。 一个只想(只想!)使过程精彩的人是无法被剥夺的,因为死神也无法将一个精彩的过程变成不精彩的过程,因为坏运也无法阻挡你去创造一个精彩的过程,相反你可以把死亡也变成一个精彩的过程,相反坏运更利于你去创造精彩的过程。 过程!对,生命的意义就在于你能创造这过程的美好与精彩,生命的价值就在于你能够镇静而又激动地欣赏这过程的美丽与悲壮。 有位大物理学家说过:“物理学不告诉我们世界是什么,而是告诉我们关于世界我们能够谈论什么。” 历史难免是一部御制经典,文学要弥补它,所以看重的是那些沉默的心魂。 佛嘛,心中无佛什么事都敢干。 丑弱的人和圆满的神之间,是信者永远的路。 ...

<span title='2022-08-23 13:25:15 +0800 +0800'>August 23, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

FFmpeg 基本使用

最近接手公司一个视频相关项目, 也是使用ffmpeg工具. 需要快速了解下. 概念 码率, 帧率, 文件大小 帧率(frame rate) : 视频一秒中有多少帧画面(frames per second, fps), 决定视频流畅度. interlaced: 古代黑白相机的交错扫描呈现, 描述单位i : 50i progressive: 现代整页整页呈现, 描述单位p: 60p 码率(bit rate) :视频一秒中有多少位, 决定视频的质量 ABR: 平均码率 CBR: 常量码率 VBR: 动态码率 文件大小 = 视频文件 + 音频文件 视频文件 = 码率 * 时间(s) / 8 音频文件 = 码率 * 时间(s) / 8 文件格式 不同的视频文件类型, 用户存储特定的数据流( 在 ffmpeg 中称为 containers) 可以存储声音或者视频数据. 相关缩写 encoding (E) decoding (D) video (V) audio (A) subtitles (S) 文件元数据 metadata 描述媒体文件自身的信息, 比如: ...

<span title='2022-08-19 00:14:54 +0800 +0800'>August 19, 2022</span>&nbsp;·&nbsp;3 min&nbsp;·&nbsp;潜水员

Redis 用于做分布式锁

操作 演进 加锁后进程挂掉了 加锁成功之后, 进程挂掉了没有进行解锁操作. 导致进入死锁状态. 引入 expire 设置超时时长, 自动释放 key 1 2 3 4 5 6 7 8 > setnx lock:key true > OK > expire lock:key 5 " ... do something critical ... > del lock:codehole 加锁动作 到 expire 之间挂掉了 redis 2.8 之后支持 set 拓展指令 1 > set lock:key true ex 5 nx 加锁互斥锁, 并同时设置超时时长 执行超时, 被其他进程获取到了锁 加锁之后, 本身进程执行时间超过了预先设置的 expire 的时间. 就会导致锁被提前释放. 解决方案: ...

<span title='2022-08-18 12:18:53 +0800 +0800'>August 18, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

CI/CD

CI 自动化发布流程 可重复 可快速回滚 发布流程快速 在合并的时候可以对代码进行快速验证 CD 部署流程平台化 一键部署 总结 所谓的 CI/CD 就是通过自动化操作, 比如自动化测试, 自动化部署. 使用项目拥有快速上线的能力 – 可以快速验证, 快速回滚, 快速发布.

<span title='2022-08-14 15:27:33 +0800 +0800'>August 14, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

Golang Map 介绍

本想写一篇关于 golang 中 map 底层的文章, 但是发现已经了相当不错的文章 – 字节跳动技术团队 - Golang 中 map 探究 这里只补充一下,缺少的 map 的删除操作 内部数据结构 初始化 map 是一个有"包含内容"的数据结构, 使用之前需要提前初始化, 即调用make 真正是调用源码是 runtime.makemap 获取数据 删除 源码地址 删除的关键代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // Only clear key if there are pointers in it. // # 当 Key 是指针类型的时候会去清空指针 if t.key.ptrdata != 0 { if goarch.PtrSize == 8 { *(*unsafe.Pointer)(k) = nil } else { // There are three ways to squeeze at one ore more 32 bit pointers into 64 bits. // Just call memclrHasPointers instead of trying to handle all cases here. memclrHasPointers(k, 8) } } e := add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.elemsize)) // # 当 Value 为指针类型的时候, 指针为空, 解除引用 -> GC if t.elem.ptrdata != 0 { memclrHasPointers(e, t.elem.size) } else { memclrNoHeapPointers(e, t.elem.size) } // # 讲 hash 值标记为空 b.tophash[i] = emptyOne 上述删除代码操作现象 ...

<span title='2022-08-13 14:14:30 +0800 +0800'>August 13, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

巴菲特致股东的信

概括 我为什么要读这本书? Youtuber 推荐, 好奇金融相关的知识 这本书怎样影响了我? 不要轻易地去触碰股市, 直到我真正的理解它. 书中的三句精华句子? 一个投资者如果想成功,必须将两种能力结合在一起,一是判断优秀企业的能力,一是将自己的思维和行为与市场中弥漫的极易传染的情绪隔离开来的能力 他们懂什么并不重要,更重要的是,他们知道自己不懂什么。一个投资者只要做出为数有限的正确的事,就可以避免犯重大错误 活跃股票的交易成本非常高,经常能达到一家上市公司净利润的10%或更多。 三句话总结本书 投资的时候要看重的公司的内在价值而不是市场先生的报价 减少交易次数 努力地去看透事情的本质 书摘 笔记摘自 巴菲特致股东的信:投资者和公司高管教程(原书第4版) 【美】沃伦E.巴菲特 关于巴菲特一生的成功秘诀,已经有无数人做出了评价,我个人认为可以归结为八个字:与时俱进,良性循环 “与坏人打交道,做成一笔好生意,这样的事情,我从来没有遇见过。”巴菲特的这句名言令人深思 从别人的故事里,找到自己的人生启发,这就是读书的意义所在 广受尊重的投资家兼作家菲尔·费雪(即菲利普·费雪,Phil Fisher)曾经将公司吸引股东的策略比喻为餐馆吸引顾客的策略。 一家餐馆可以定位于特定的食客阶层——喜欢快餐的,喜欢优雅的,喜欢东方食品的等。通过风格的定位,最终获得一批志同道合的拥趸。如果餐馆的服务、菜单、价格水平策略得当,那么这批客户会成为固定的回头客。但如果餐馆经常转换风格,那么这批快乐而稳定的客户就会消失。如果餐馆的定位在法式美食和外卖鸡之间摇摆不定,那么一定会令回头客感到困惑,最终离开。 应该可以直接与公司CEO进行沟通,得到他现在和未来如何对企业进行估值的看法 如果我们对一只股票有良好的长期预期,那么短期的价格波动对我们来说毫无意义,除非有人报给我们一个非常有吸引力的价格。 芒格和我无法向你承诺结果。但我们可以保证,只要你是我们的合伙人,在任何时段,你的金融资产和我们自己的资产将完全保持一致的成长 为了达成目标,我们的首选是直接持有一系列多元化的企业,从中获得稳定的现金流和持续的高于市场平均水平的资本回报 从整体和长期来看,我们希望那些未体现的盈利,通过资本增值的形式体现在我们的内在价值里 巴菲特以及伯克希尔避免进行预测,因为这是一种糟糕的管理习惯,经常会导致管理人粉饰报表 但是任何短期的压力都不应以牺牲长期竞争力为代价 一场大会的毫无建树是由于参与股东们更在意自己在台上的表现,而不是关心公司运营的状况 在伯克希尔公司,我们通常会换位思考,设想如果我们自己处于股东的位置,应该得到什么样的信息,我们会从这样的角度向股东披露完整的报告 这种打假活动针对的目标是公司信息披露行为中的“选择性披露”,近些年来,这种选择性披露行为像癌症一样蔓延。的确,信息的选择性披露已经成为大型公司的一种标准化的行为 CEO们预测公司增长速度,是骗人的和危险的。当然,他们是被分析师和公司自己的投资者关系部门怂恿裹挟着这么做。但他们应该拒绝,因为这样预测多了会招致麻烦。 厨房里如果有蟑螂,绝不可能只有一只 在一个由一群和事佬组成的董事会里,不太可能会有人提出更换CEO的提议。同样,也不可能对CEO提议的公司并购活动提出质疑 毕竟,没有人会喜欢去洗外面租来的车 除了要维持独立性,董事们也必须具备丰富的商业经验,以股东利益为导向,以及在公司拥有真正的利益 在收购之前,他们就已是商界的管理明星,已经证明了自己在各自领域中的才华,我们的主要贡献就是让他们自由发挥天分,不给他们添乱 “如果我们雇用的都是比我们矮的人,我们将成为一家侏儒公司;但如果我们雇用的都是比我们高的人,我们会成为一家巨人公司。” 我们希望我们的经理人队伍考虑什么是重要的,而不是考虑什么被认为是重要的。 当投资的时候,我们将自己视为企业分析师——而不是市场分析师,不是宏观经济分析师,甚至不是证券分析师。 他说你应该将市场报价想象为一个名叫“市场先生”的人 如果你不懂得你的公司,不能比市场先生更准确地评估你的公司,你就不要参与这场游戏 就像人们打牌时说的:“如果玩了30分钟,你还不知道谁是倒霉蛋,有可能就是你。 一个投资者如果想成功,必须将两种能力结合在一起,一是判断优秀企业的能力,一是将自己的思维和行为与市场中弥漫的极易传染的情绪隔离开来的能力 有些人会在不同市场间倒手,意图赚取差价。你不必感到惊讶,从业者为此选了一个法语词汇:套利。 如果需要同时做很多事情,就像同时将很多烙铁放在火中,人们就必须花大量的时间,既要监控交易的过程,又要监控市场股价的波动。这不是芒格和我所想的生活模式。(如果只是为了赚钱而整天盯着股票行情,这种生活有什么意义可言? 在完全忽视股价的情况下,一家拥有子公司的母公司,如果子公司长期表现优异,母公司是不可能出售子公司的。“为什么要卖出?”CEO会问,“难道要我卖出皇冠上的宝石吗 应该评估是否在其预期的持股期间,其投资的税后收益总和(包括他卖出所得)会带给他至少在投资开始之初同等的购买力,加上合理的利率因素 一个视力平平的人,没有必要在干草堆里寻找绣花针。 我们的座右铭是:“如果你一开始就取得了成功,那么,不必再做测试。 很多大名鼎鼎的基金管理人现在关注的是其他基金管理人未来几天干什么,而不是关注企业未来几年干什么。对于他们而言,股票仅仅是游戏中的筹码,就像大富翁游戏中,如同顶针和熨斗一样的道具 我们的目标是发现那些价格合理的杰出公司,而不是价格便宜的平庸公司 最值得拥有的公司是,那些在一个一直延伸的时期周期里,可以不断利用增量资本获得很高回报率的公司 他们懂什么并不重要,更重要的是,他们知道自己不懂什么。一个投资者只要做出为数有限的正确的事,就可以避免犯重大错误 二级市场经常周期性地被大量傻瓜所主导,会持续设定一个“清算”价格。无论这个价格多么愚蠢,它是股票或债券持有者需要或希望卖出的价格,总是有这样的机会出现 无论什么样的天才或努力,有些事情总是需要时间。即便你能让九个女人同时怀孕,也不可能让她们在一个月的时间里生出小宝宝。) 但我更喜欢一个确定的良好结果,而不是一个期望的伟大结果。 在企业内部,有一种看不见的力量足以压倒一切,我们可以称其为“惯性驱使”或“机构强迫症” 如果我们在资产负债表上使用适当的负债,可以在安全的前提下增加一些盈利 信用就像氧气。此二者,在充足的时候,人们不会注意到它们的存在;当它们消失的时候,人们才会发现它们的重要性 当年花1美元可以买到的东西,今天要花7美元以上。因此,即便一个不用交税的机构,也必须在同期从债券上获得4.3%的年化利息收入,才能维持其购买力不变。如果这些机构的管理人将任何的利息部分视为“收入”的话,他们一定是在和自己开玩笑 即使在最混乱的经济环境中,美国国债也是唯一靠得住的流动性良好的投资对象 大多数人宁愿去死,也不愿意思考。很多人就是这样 巨大的负债可以让管理层前所未有地专注工作,就像在汽车方向盘上装一把匕首,可以提高司机的注意力一样 衍生品还可能造成连锁反应式的风险,因为很多保险公司或再保险公司将它们的风险分散给其他保险公司 ...

<span title='2022-08-08 13:27:29 +0800 +0800'>August 8, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

Mysql- 数据类型 - 数字

概览 Mysql 支持以下数据类型 数字类型 串类型(字符和字节) 日期和时间 空间 JSON 数字类型 整数类型 Interger 类型 存储大小 bytes 其他别名 TinyInt 1 bool, boolean = tinyint(1) SmallInt 2 MediumInt 3 Int 4 BigInt 8 int(M) 表示显示宽度, 最大显示宽度为(255), M 与存储空间的大小无关. 空间大小由具体类型决定. 如果具体数值达不到宽度, 左边就会用0值补齐至 M 位. 浮点 ( Floating-Point ) 类型 存储 补充 范围 Float 4 bytes 单精度 Double 8 bytes 双精度 Float(p) p 表示小数点后的精度位数 Float(M, D) Mysql 语法: M表示总显示位数, D表示小数点后个数 – 由Mysql自己做约分处理. Mysql 8.0 后废弃该语法. ...

<span title='2022-07-31 17:49:46 +0800 +0800'>July 31, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

Mysql- 数据类型 - 日期

概览 Mysql 支持以下数据类型 数字类型 串类型(字符和字节) 日期类型 空间 JSON 日期类型 Mysql 支持的数据类型 DATE TIME DATETIME TIMESTAMP YEAR Date 只存储日期数据, 不包含时间. YYYY-MM-DD, 范围是从 ‘1000-01-01’ to ‘9999-12-31’ DateTime 存储日期, 也存储时间 'YYYY-MM-DD hh:mm:ss' 范围是从'1000-01-01 00:00:00’ to ‘9999-12-31 23:59:59’ TIMESTAMP 存储Unix时间戳数据 会受到服务器时区影响– 存储的时候转化成标准的Unix时间戳(0时区), 取数据时反之 时区环境变量设置 范围 ‘1970-01-01 00:00:01’ UTC to ‘2038-01-19 03:14:07’ UTC. 相关函数: FROM_UNIXTIME 把 Unix 时间戳转化成日期 UNIX_TIMESTAMP 把日期转化成 Unix 时间戳 YEAR 显示形式 YYYY, 可选显示位数YYYY(M) 默认4位显示 ‘1991’ TIME 只有时间部分,没有日期部分 hh:mm:ss, 范围从 ‘-838:59:59’ 到 ‘838:59:59’ ...

<span title='2022-07-31 17:49:46 +0800 +0800'>July 31, 2022</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;潜水员

xorm 的 session 和 salve 的区别

简单分析下xorm 里面 session 和 slave 里面 close 的代码 1 xorm.EngineGroup.Slave() Slave () 会直接返回 xorm.Engine对象(指代我们项目到数据库的逻辑连接(里面有tcp复用)) 如果这时候再调用 close 的会,会直接把 xorm.Engine 关闭(即数据库连接关闭)。 如果用这个 engine, 执行查询动作如 find, get时. 内部会有自动执行 NewSsession 和 Close, 所以不在需要手动调用close 1 xorm.EngineGroup.NewSsession() 会返回一个xorm.Session对象, 对应我们数据库操作中的"会话事务", 是否自动提交之类选项.(未手动开始事务时,都是自动提交) 调用 close, 对清除 session 中未提交的事务和一些缓存的 sql 前置处理语句 对于普通 select 语句调不调用是没什么太大影响 (但是还是建议new之后调用close)

<span title='2022-07-22 19:08:05 +0800 +0800'>July 22, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

Make 的基本使用

想自己整理一篇基本的 make 指令用法, 突然发现 阮一峰大佬已经整理了一篇很完整的博客, 遂放弃. 阮一峰文章地址 如果不写 c, 主要理解就几个概念就可以使用了 target 可以用来当作想要执行的命令集的名称 .PHONY: 可以用来声明命令集名称 recipes 实际执行的命令集合 介绍一下我自己的应用场景 我目前主力编程语言是 go, 我用的编辑器是 vim, 所以我基本就在 shell 里面完成编码任务. case 1: 简化本地编译和测试, 自动做 setup 和 teardown 当我想要尝试一下整个项目是否编译 1 2 3 4 .PHONY: build build: go build . rm -rf [PROJECT NAME] 使用上面的 makefile, 我就只需要 make build, 就不用再删除编译出来文件. QAQ, 可以再加一些单元测试命令, 检测测试是否通过. 因为公司的项目, 在单测这方面做的不是很好, 我自己就是简单 build 一下 case 2: git 提交代码自动化操作 当我想要把我代码推送到, 测试分支, 进行集成测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 .PHONY: dev ProjectName="Your Project Name" TargetBranch="Your want to merge branch" CurBranch=$(shell git branch --show-current) dev: go build . rm -f $(ProjectName) git add . git commit -m $(msg) git push git checkout ${DevBranch} git pull --rebase git merge ${CurBranch} -m "Merge branch '${CurBranch}' into ${DevBranch}" go build rm -f $(ProjectName) git push git checkout ${CurBranch} 简化 git 的操作流程, 现在只需要make dev就可以完成, 还可以在合并之前和之后增加测试, 我自己目前知识简单的 build 下而已 QAQ. ...

<span title='2022-07-10 17:47:42 +0800 +0800'>July 10, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

RabbitMQ 基本入门实践

公司刚好有一个项目要使用到 RabbitMQ, 本文是我自己了解学习 RabbitMQ 的记录. 介绍一下 RabbitMQ Erlang 语言实现 AMQP (Advanced Message Queuing Protocal) 的消息中间件 消息中间件的作用 解耦: 可以不需要依赖下游的可用性, 提高单独项目的可用性. 冗余存储: 保存失败的消息 拓展性 削峰 缓冲 结构 涉及的名词简单解释 Producer Consumer Broker: 服务节点 Queue: 内存存储消息数据的对象 Exchange: 选择器, 生产者投递消息后, 提交给交换器, 由交换器根据routingkey 和 bindingkey 决定投递到哪个队列 RoutingKey: 生产消息提供routingkey 给交换器用于指定要投递的队列 BindingKey: 交换器, 通过 bindingkey 与对应的队列关联起来 Connection: 客户端与 Broke 建立的 TCP 连接 Channel: 是建立在 Connection 上抽象的虚拟连接. 实现多线程可以 TCP 连接, 多个信道可能复用同一个 TCP 连接 交换器的类型 fanout : 投递到所有队列 direct: 投递到 routingkey 和 bindingkey 匹配的 topic: direct 的拓展, 支持模糊匹配 headers : 性能差, 少用 消息投递流程: ...

<span title='2022-07-09 16:43:26 +0800 +0800'>July 9, 2022</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;潜水员

我理解的微服务 -- 读《微服务设计模式》总结

微服务是针对公司某一复杂业务程序实现的设计模式, 与巨石架构(Monolith)是相对的. 微服务对应的应该是公司业务能力层级上的拆分与设计, 为了减少业务之间的耦合而导致相互拖累, 在对外业务能力不变的情况下, 在应用内部将能力拆分成一些微小服务. 也可以理解为是对巨石架构进行"解耦". 举个例子: 原先公司做的是一个外卖系统, 这个系统中可能包含了客户下单, 商家接单, 骑手配送等功能. 但是全部都打包在一个程序中. 发版时, 可能客户下单功能修改了功能, 导致商家没办法接单了. 或者商家接单功能实现的有问题, 导致整个应用程序挂掉, 现在用户下不了单, 骑手也没法接单, 整个公司的业务就瘫痪了. 然后, 在客户下单-商家接单-骑手配送这个大业务流程不变的情况下, 我们在外卖系统内部, 分成了多个服务, 各个服务之间使用 API 松耦合通信, 隔离影响. 比如, 客户下单服务, 专门处理客户下单这一业务, 并将生成的订单推送到消息代理 (如:kafka) 或直接推送给其他服务等, 它只要能保证完成它的职责即可. 后者, 就可以称之为 “微服务架构”. 当然, 这只是一个例子, 实际情况会更加复杂. 在«微服务设计模式» 中对微服务的定义: 将应用程序构建为松耦合, 可独立部署的一组服务 书中也对"微"的大小给了定义: 大小的定义为能够由小团队开发服务 不用刻意地去追求服务的大小. 微服务的落地, 往往就会伴随着, 组织结构和开发的流程的改变, 由不同的 小团队 独立负某一服务. 像我们现在如果提到微服务, 就经常也会提到一些微服务框架 go-zero, go-micro 或者基础设施 docker, k8s 或者工具 gRPC, prometheus 之类的. 像这种框架和组件之类的只是一种技术工具. 他们并不能定义微服务, 他们可能只是为了克服微服务架构设计带来的某一些缺陷, 或者与微服务结合可以发挥出更大的价值. ...

<span title='2022-06-19 22:20:56 +0800 +0800'>June 19, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

什么是 "胶水代码"

胶水代码(glue code), 可以了解为是大号的适配器, 没有业务意义, 主要的目的是用于 连接 两个 不兼容 的组件, 或是两个不兼容的服务. 胶水代码可以是一段代码, 也可以是一个脚本文件, 甚至可以是新的组件. 参考 Quora 回答 wiki

<span title='2022-06-18 20:04:38 +0800 +0800'>June 18, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

Go中slice[i:j:k]第三个参数是做什么的

今天, 突然被同事卷到了, 被问到 golang 中 slice 的三个参数是干嘛的? 我突然一时间忘记了, golang 的重切片居然是可以接受第三个参数的, 枉费我已经了写了快两年的 go 了. 赶紧 google 一下, 并总结备忘. 简单介绍 slice 的数据结构 首先, 介绍一下 golang 中切片的结构体: 1 2 3 4 5 type slice struct { array unsafe.Pointer len int cap int } 有三个字段: array 是切片所指向的底层数组数据 len 就是切片的长度 cap 即容量, 很明显 源码地址 简单版重切片 a[low:high] 接受切片中的开始下标和结束下标, “左闭右开原则” 即重的切片数据会包含 low 下标的值, 但没有 high 下标的值 新切片的 容量(cap) 即为开始下标到原 slice 数据容量结束, 即"cap(a) - low" low 参数可以省略, 默认从 0 下标开始 high 参数也可以省略, 默认就是 slice 的长度, 即 len 的 value 1 2 3 4 5 6 7 8 a := [10]int{} oldSlice := a[:5] newSlice := a[2:4] fmt.Printf("b: len %d, cap %d, c: len %d, c:cap %d", len(b), cap(b), len(c), cap(c)) 输出: b: len 5, cap 10, c: len 2, c:cap 8 底层分配情况如下: ...

<span title='2022-06-09 23:52:30 +0800 +0800'>June 9, 2022</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;潜水员

设计模式 -- 策略模式

场景 在有多种算法, 计算策略, 甚至业务流程以一种可相互替换的场景出现时. 就可以考虑该设计模式. 比如: 地图导航的出行路线计算, 商品购买的捆绑促销方式等. 分析 优点: 将具体的策略与调用策略的流程代码解耦, 修改策略代码时候可以仅修改策略对象 在不同策略之间划清界限 增加单独策略的可测试性 缺点: 后续变更有一定束缚性 ( 限制在抽象接口中 ) . 若需要打破策略的抽象接口, 就会造成较大的改动 会带来的问题: 可能将原先一个流程代码, 拆分成了多分. 如果代码结构没有组织好, 想要大局把握可能比较费力 总结: 在流程算法策略有多个 ( 如果只有一个就没有必要抽象了, 一梭子写完就行 ), 且各个策略都有一定复杂性 ( 只是简单几个 if 的也略了吧 ) 的场景下. 就可以使用 ( 接口的签名可以写的比较松一点, 传递和返回较高层级的数据对象 ). 实现流程 主要的思想, 我觉得还是 面向接口编程 分析要拆分的算法或者策略, 将主流程和策略部分, 提取抽象成一个通用接口(interface) 将算法或策略剥离成独立的策略对象, 并实现上述抽象接口 主流程代码根据业务逻辑, 初始化策略对象, 将需要的策略"插入"(plugin)流程, 调用, 获取结果, ok. 参考 refactoringguru - strategy

<span title='2022-06-08 19:50:42 +0800 +0800'>June 8, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

计算机中的:大端和小端

大端和小端的命名出处是来自于《格列佛游记》中吃鸡蛋分成从大端开始吃的“大端派”和从小端开始吃的“小端派” 大端的优势是高位计算,和可读性 小端的优势的低位运算 各自的优劣分析本质上还是因为内存的连续性,需要修改和读取的位数越少越有优势。 以上是阅读阮一峰的博文-字节序探析:大端与小端的比较的简单总结。本来自己也是想要整理一篇关于大小端分析的文章。刚好阮老师发文了,收获甚多,就不在自己整理了。 参考连接 阮一峰的博文-字节序探析:大端与小端的比较

<span title='2022-06-04 00:19:23 +0800 +0800'>June 4, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

小窥 Go 中的 Modules

是什么 Modules (下文称为模块)是 Go 语言设计用来管理依赖包。 在中文中我们经常把go中的 Module 和 Package 统称为“包”,其实 Module 是一个版本控制的“包”的集合。 模块的引入主要用于解决,项目依赖的不同版本的问题。(在旧的 GOPATH 中不同项目依赖不同版本)。引入的模块会声明在go.mod文件中。 go.mod 文件 1 2 3 4 5 6 7 8 9 module example.com/my/thing go 1.12 require example.com/other/thing v1.0.2 require example.com/new/thing/v2 v2.3.4 exclude example.com/old/thing v1.2.3 replace example.com/bad/thing v1.4.5 => example.com/good/thing v1.4.5 retract [v1.9.0, v1.9.5] 文件中各行意思 module 当前自己模块的名的完整路径 go 版本号 require 需要依赖的目标模块以及最小的版本号 exclude 排除目标模块的特定版本 replace 将某个模块版本指向另一个模块版本,也可以指向本地,未发布的模块 retract 当前发布的模块,需要撤回不能用版本,用于处理意外发布版本的情况 go.mod 可以通过相关命令修改,也可以直接修改文件数据 go.sum 文件 与go.mod经常在一起的会是一个go.sum文件,文件中存放着第一次添加依赖模块时,的模块源码的 hash 值。主要是用于校验,防止依赖模块代码被意外地修改到。 ...

<span title='2022-06-03 18:16:55 +0800 +0800'>June 3, 2022</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;潜水员

Mysql 不支持事务嵌套

mysql 在事务中再开启事务,前一个事务会被自动提交 stackoverflow

<span title='2022-06-02 16:16:58 +0800 +0800'>June 2, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员

并发与并行的区别

举个例子,电脑的鼠标,键盘或者其他设备的驱动程序,他们是并发的,但不是并行的。他们也不需要并行去运行。 并发是很多程序(形容运行任务,不是广义上的程序)的独立运行,并发是一种程序设计结构 并行是一次性运行很多程序,并行是一种程序的运行现象,当成程序设计成并发的,他很容易就变成了并行, 但并行不一定是并发的目的。 Concurrency is not Parallelism by Rob Pike

<span title='2022-05-31 22:36:34 +0800 +0800'>May 31, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;潜水员