PHP 8 新特性

PHP 8 新特性 命名参数(8.0) 新增命名参数的功能: 在函数或方法调用时,可通过参数名来指定参数的值,而不仅仅依赖参数的位置 从 PHP 8.0.0 开始,函数参数列表可以包含一个尾部的逗号,这个逗号将被忽略。这在参数列表较长或包含较长的变量名的情况下特别有用,这样可以方便地垂直列出参数。 <?php function takes_many_args( $first_arg, $second_arg, $again = 'a default string', // 在 8.0.0 之前,这个尾部的逗号是不允许的。 ){ // ... } z takes_many_args(1, 2); //按照参数顺序传参 takes_many_args(first_arg:1, second_arg:2); //指定参数,不分顺序 // 类也可以使用命名参数,假设Demo类构造函数有$first_arg,$second_arg,两个参数,有takes_many_args方法 $demo = new Demo(first_arg:1, second_arg:2); $demo->takes_many_args(first_arg:1, second_arg:2); // 不能用位置的参数和命名的参数一起 // 可选参数必须在必选参数后面 例如上面的$again ?> 注解(Attributes)(8.0) 新增注解的功能。 此篇单独介绍 构造器属性提升(Constructor Property Promotion)(8.0) 新增构造器属性提升功能 在构造函数中声明类的属性)。 构造器的参数也可以相应提升为类的属性。 构造器的参数赋值给类属性的行为很普遍,否则无法操作。 而构造器提升的功能则为这种场景提供了便利。 <?php class Point { protected int $x; protected int $y; public function __construct(int $x, int $y = 0) { $this->x = $x; $this->y = $y; } } // 两个参数都传入 $p1 = new Point(4, 5); // 仅传入必填的参数。 $y 会默认取值 0。 $p2 = new Point(4); // 使用命名参数(PHP 8....

May 11, 2023 · 4 min · Leanku

项目规范指南

项目规范指南 本规范适用于团队/开源项目的版本管理,目标是做到:规范化、可追踪、可溯源。 1. 版本管理 (Versioning) 遵循 语义化版本规范 (Semantic Versioning, SemVer 2.0.0) MAJOR.MINOR.PATCH MAJOR:主版本号,不兼容的 API 改动 MINOR:次版本号,新增功能(向下兼容) PATCH:修订号,修复 bug(向下兼容) 先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。 预发布版本:1.0.0-alpha.1、2.0.0-rc.1 参考语义化版本规范:https://semver.org/lang/zh-CN/ 2. LICENSE (MIT) 作用:MIT,明确版权 规范 项目必须包含 LICENSE 文件,放置于项目根目录。 推荐使用 MIT License(宽松、常用,几乎所有开源项目可接受)。 文件名统一:LICENSE(不要写成 LICENSE.txt 或 license.md)。 在 README.md 中需明确说明 License 类型。 示例 LICENSE 文件(MIT): MIT License Copyright (c) 2025 Your Name Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal ....

April 1, 2023 · 2 min · Leanku

PHP8新特性之match表达式

PHP8 alpha2发布了,最近引入了一个新的关键字:match, 这个关键字的作用跟switch有点类似。 虽然我一般对语法糖无感,但这个我觉得还是有点意思,match这个词也挺好看,那么它是干啥的呢? 在以前我们可能会经常使用switch做值转换类的工作,类似: switch ($input) { case "true": $result = 1; break; case "false": $result = 0; break; case "null": $result = NULL; break; } (当然,有的同学会说,谁会这么写,用个数组转换不行么? 拜托,这是举例啊,数组也只能数字键和整数啊,万一key是需要其他表达式呢,万一你要多个key对应一个值呢,对吧?) 那么如果使用match关键字呢,可以变成类似: $result = match($input) { "true" => 1, "false" => 0, "null" => NULL, }; 相比switch, match会直接返回值,可以直接赋值给$result了。 并且,类似switch的多个case一个block一样,match的多个条件也可以写在一起,比如: $result = match($input) { "true", "on" => 1, "false", "off" => 0, "null", "empty", "NaN" => NULL, }; 需要注意的和switch不太一样的是,以前我们用switch可能会经常遇到这种诡异的问题: $input = "2 person"; switch ($input) { case 2: echo "bad"; break; } 你会发现,bad竟然被输出了,这是因为switch使用了宽松比较(==)。match就不会有这个问题了, 它使用的是严格比较(===),就是值和类型都要完全相等。...

March 14, 2023 · 1 min · Leanku

B+Tree

B+Tree B+Tree 是一种平衡多路搜索树,广泛应用于数据库和文件系统等领域,其核心优势在于优化磁盘存储效率和查询性能. MySQL的InnoDB存储引擎使用的索引结构就是 B+树,它是B树的一个重要变种。 1. 从B树到B+树 B树:一种自平衡的、多路的搜索树。它允许每个节点有多个子节点(多于两个,所以不是二叉树)。 B+树:在B树基础上优化而来的数据结构,是现代数据库系统中事实上的标准索引结构。 MySQL的InnoDB使用的正是 B+树。 2. 为什么数据库需要B+树? 要理解B+树,必须先理解它的设计目标。数据库的数据存储在磁盘上,磁盘I/O(读写磁盘)的速度比内存访问慢几个数量级。因此,数据库索引的核心目标是:最大限度地减少磁盘I/O次数。 B+树通过以下方式完美地实现了这一目标: 矮胖:与“瘦高”的二叉树相比,B+树每个节点可以存储非常多的键,这使得树的层级非常少(通常只有3-4层),从而保证在亿万级数据量下,查找任何一条记录最多只需要3-4次磁盘I/O。 顺序访问友好:B+树非常适合磁盘的预读特性,能够高效地进行范围查询。 3. B+树的详细结构 它由两种类型的节点组成:内部节点 和 叶子节点。 内部节点(非叶子节点) 作用:仅充当导航目录。 存储内容:只存储键值(索引列的值)和指向子节点的指针。 不存储:实际行的数据。 叶子节点 作用:存储实际的数据。 存储内容: 在 主键索引(聚簇索引) 中:叶子节点存储的就是完整的行数据。 在 辅助索引(二级索引) 中:叶子节点存储的是该索引的键值和对应的主键值。 关键特性:所有叶子节点通过指针相互连接,形成了一个有序的双向链表。这是B+树与B树的一个核心区别。 4. B+树的核心特性与优势(对比B树) 特性 B树 B+树 B+树的优势 数据存储位置 内部节点和叶子节点都存储数据。 只有叶子节点存储数据,内部节点仅为索引。 更“矮胖”的树。因为内部节点不存数据,所以一个节点能容纳的键更多,扇出(子节点数)更大,树高更低,I/O次数更少。 叶子节点链接 叶子节点之间没有链接。 叶子节点通过双向链表连接。 无敌的范围查询。要查询age BETWEEN 20 AND 30的所有记录,B+树只需找到20,然后顺着链表遍历即可。B树则需要不断地在树的中上层和下层之间来回跳跃,性能极差。 扫描和全表遍历 需要对整棵树进行复杂的中序遍历。 只需遍历底层的链表即可获得所有数据,非常高效。 对数据仓库、聚合查询等场景非常友好。 查询稳定性 由于数据可能在内部节点找到,查询时间不稳定。 任何查询都必须走到叶子节点,查询时间非常稳定。 保证了可预测的性能。 5. 在MySQL中的具体体现:聚簇索引 在MySQL InnoDB中,主键索引就是一颗B+树,并且这棵B+树的叶子节点直接存储了完整的行数据。这种索引组织表的方式被称为“聚簇索引”。 表数据文件本身就是按B+树结构组织的一个索引文件。 如果你没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有这样的索引,它会隐式地定义一个主键。 辅助索引(二级索引) 也是一颗B+树,但它的叶子节点存储的是该索引列的值和对应记录的主键值。当通过二级索引查找数据时,需要先找到主键,再回到主键索引(聚簇索引)中查找完整数据,这个过程称为“回表”。...

March 12, 2023 · 1 min · Leanku

常用算法的PHP实现

常用算法的PHP实现 1. 快速排序 (Quick Sort) <?php function quickSort($arr) { if (count($arr) <= 1) { return $arr; } $pivot = $arr[0]; $left = $right = []; for ($i = 1; $i < count($arr); $i++) { if ($arr[$i] < $pivot) { $left[] = $arr[$i]; } else { $right[] = $arr[$i]; } } return array_merge(quickSort($left), [$pivot], quickSort($right)); } // 测试 $numbers = [64, 34, 25, 12, 22, 11, 90]; echo "原始数组: " . implode(', ', $numbers) ....

March 12, 2023 · 3 min · Leanku

数据结构

数据结构 一、说明 数据结构是计算机科学中一个非常基础和核心的概念,它对于编程、算法设计和软件工程都至关重要。 简单来说,数据结构是一种在计算机中组织、管理和存储数据的方式,目的是为了实现高效地访问和修改。 可以把它想象成一个储物系统: 把一堆书随便堆在地上,这是一种“存储”,但找起来非常困难。 使用一个带标签的书架,把书分门别类地放好,找书、放书就高效得多。 这个“书架”以及“如何给书分类、摆放”的规则,就是一种“数据结构”。 为什么数据结构如此重要? 选择合适的数据结构可以极大地影响程序的性能和效率。一个精心选择的数据结构可以让操作(如搜索、插入、删除)变得非常快;而错误的选择则可能导致程序运行缓慢甚至崩溃。 二、 常见的数据结构分类和类型 数据结构主要可以分为两大类:线性结构和非线性结构。 一、 线性数据结构 元素按顺序排列,形成一条“线”。 数组:在内存中连续存储相同类型的元素。通过索引可以快速访问任意元素。 优点:随机访问速度快。 缺点:大小固定(在某些语言中),插入和删除元素效率低。 链表:由一系列节点组成,每个节点包含数据和指向下一个节点的指针。 优点:大小动态,插入和删除元素效率高。 缺点:不能随机访问,必须从头开始遍历。 栈:一种后进先出的结构,像一摞盘子。只能在顶部进行添加(压栈)和移除(弹栈)操作。 应用:函数调用栈、撤销操作、表达式求值。 队列:一种先进先出的结构,像排队一样。从队尾添加元素,从队首移除元素。 应用:任务调度、消息队列、广度优先搜索。 变种:双端队列、优先队列。 二、 非线性数据结构 元素之间不是简单的前后关系,可能存在多个连接。 树:一种分层结构,由节点和边组成。最顶端的节点叫根节点。 二叉树:每个节点最多有两个子节点。 二叉搜索树:左子树所有节点的值小于根节点,右子树所有节点的值大于根节点。这使得搜索非常高效。 应用:文件系统、数据库索引、决策树。 图:由顶点和连接顶点的边组成。可以表示任意复杂的关系网络。 应用:社交网络、地图导航、网络路由。 哈希表:通过一个哈希函数将键映射到一个位置来访问记录,以实现极快的查找速度。 优点:在平均情况下,插入、删除和查找的时间复杂度都是 O(1)。 应用:字典、集合、缓存。 三、核心操作与算法 对于每种数据结构,我们通常关心以下几个核心操作的效率: 访问 搜索 插入 删除 这些操作的效率通常用 大O表示法 来衡量,它描述了算法时间或空间复杂度随数据规模增长的趋势。 四、作用 数据结构是构建高效算法的基石。学习数据结构能帮助你: 写出更高效的代码:理解不同操作的代价。 解决复杂问题:很多复杂问题本质上就是数据组织和处理的问题。 更好地理解计算机系统:从内存管理到数据库,底层都离不开数据结构。

March 12, 2023 · 1 min · Leanku

算法

算法 算法是计算机科学的核心基础之一,简单来说它是解决特定问题的一系列清晰指令。无论是简单的计算还是复杂的人工智能任务,都离不开算法。 1. 算法是什么? 你可以把算法想象成一个菜谱: 输入:食材(数据) 处理步骤:清晰的烹饪步骤(算法逻辑) 输出:一道菜肴(结果) 它的核心目标是用最优的方式(最快、最省资源)解决问题。 2. 算法的核心特性 一个“好”的算法通常具备以下特点: 正确性:必须能正确解决问题。 高效性:执行时间和占用空间要尽可能少。 明确性:每一步都必须清晰、无歧义。 有限性:必须在有限的步骤内结束。 3. 常见的算法类别与实例 算法种类繁多,以下是一些主要类别和经典例子: 排序算法 快速排序:采用“分治”思想,选择一个基准元素,将数组分成左右两部分,效率很高。 归并排序:也是“分治”思想,先将数组不断拆分,再合并排序,稳定且高效。 冒泡排序:反复交换相邻的逆序元素,简单但效率低。 搜索算法 二分查找:在已排序的数组中,每次比较都能排除一半的数据,效率极高(O(log n))。 深度优先搜索和广度优先搜索:用于遍历或搜索树和图结构,是许多复杂算法的基础。 图算法 Dijkstra算法:用于寻找图中两点之间的最短路径。 A*搜索算法:在Dijkstra基础上加入了启发式函数,是路径规划和游戏AI的基石。 动态规划 用于解决具有重叠子问题和最优子结构的复杂问题(如斐波那契数列、背包问题),通过存储中间结果来避免重复计算。 机器学习算法(AI领域) 线性回归/逻辑回归:用于预测和分类。 决策树/随机森林:通过树形结构做决策。 支持向量机:寻找最佳分类边界。 神经网络:模仿人脑神经元,是深度学习的核心。 4. 如何衡量算法的好坏?—— “复杂度分析” 我们使用 “大O表示法” 来描述算法的效率,主要看: 时间复杂度:随着数据规模增大,算法运行时间的增长趋势。例如 O(1), O(log n), O(n), O(n²)。 空间复杂度:随着数据规模增大,算法占用内存空间的增长趋势。 5. 为什么算法如此重要? 效率:好的算法能处理海量数据,差的算法在大数据面前寸步难行。 性能:直接影响软件和应用的反应速度与用户体验。 解决问题的基础:是开发任何软件系统、进行科学计算和实现人工智能的基石。 面试核心:是国内外大型科技公司技术面试的必考内容。

March 12, 2023 · 1 min · Leanku

我步入丛林

我步入丛林,因为我希望生活的有意义,我希望活的深刻。汲取生命中所有的精华,把非生命的一切都击溃,以免让我在生命终结时,发现自己从来没有活过! I went to the woods because I wanted to live deliberately. I wanted to live deep and suck out all the marrow of life!To put to rout allthat was not life, and not, when I had come to die, discover that I had not lived. 推荐电影《死亡诗社》 原文出自 《瓦尔登湖》-亨利·戴维·梭罗

March 12, 2023 · 1 min · Leanku

记录一些句子

记录一些句子 你是否也曾被一句话深深触动?还记得吗? 生活 刀枪入库,马放南山。- 清代.钱彩.《说岳全传》 先去你的塞外,再回我的江南。 -金庸.《天龙八部》 小舟从此逝,江海寄余生。 - 《临江仙·夜饮东坡醒复醉》 行到水穷处,坐看云起时。 - 《终南别业》 道 上善若水,水利万物而不争。 - 《道德经》 朝闻道,夕死可矣。 ——《论语·里仁》 天下同归而殊途,一致而百虑。 ——《易经·系辞下》 大方无隅,大器晚成,大音希声,大象无形。 - 《道德经》 为天地立心,为生民立命,为往圣继绝学,为万世开太平。 - 《横渠语录》 相濡以沫,不如相忘于江湖。 - 《庄子》 苟日新,日日新,又日新。 - 《大学》 慎终如始,则无败事。 - 《道德经》 为者常成,行者常至。 - 《晏子春秋》 一念起天涯咫尺,一念灭咫尺天涯。

March 12, 2023 · 1 min · Leanku

docker删除none镜像

docker删除none镜像 1、使用git bash进入到docker文件夹 2、查询所有的none镜像 docker images | grep none 3、查询所有的none镜像的id docker images | grep none | awk '{print $3}' 4、删除所有的none镜像 docker images | grep none | awk '{print $3}' | xargs docker rmi docker none镜像说明 一、有效的 none 镜像 Docker文件系统的组成,docker镜像是由很多 layers组成的,每个 layer之间有父子关系,所有的docker文件系统层默认都存储在/var/lib/docker/graph目录下,docker称之为图层数据库。 最后做一个总结< none>:< none> 镜像是一种中间镜像,我们可以使用docker images -a来看到,他们不会造成硬盘空间占用的问题(因为这是镜像的父层,必须存在的),但是会给我们的判断带来迷惑。 二、无效的 none 镜像 另一种类型的 < none>:< none> 镜像是dangling images ,这种类型会造成磁盘空间占用问题。 像Java和Golang这种编程语言都有一个内存区,这个内存区不会关联任何的代码。这些语言的垃圾回收系统优先回收这块区域的空间,将他返回给堆内存,所以这块内存区对于之后的内存分配是有用的 docker的悬挂(dangling)文件系统与上面的原理类似,他是没有被使用到的并且不会关联任何镜像,因此我们需要一种机制去清理这些悬空镜像。 我们在上文已经提到了有效的< none>镜像,他们是一种中间层,那无效的< none>镜像又是怎么出现的?这些 dangling镜像主要是我们触发 docker build 和 docker pull命令产生的。 使用下面的命令可以清理 docker rmi $(docker images -f "dangling=true" -q)

March 11, 2023 · 1 min · Leanku