接口型函数
最近在写极客兔兔的GeeCache这个小项目,在里面遇到了一段不太理解的代码, 1234567891011type Getter interface { Get(key string) ([]byte, error)}// A GetterFunc implements Getter with a function.type GetterFunc func(key string) ([]byte, error)// Get implements Getter interface functionfunc (f GetterFunc) Get(key string) ([]byte, error) { return f(key)} 结合兔兔的讲解,写一篇博客 本质是实现多态 接口只有一个方法,为什么不直接使用GetterFunc作为参数传进参数? 12func GetFromSource(fn GetterFunc, key string)...
JWT
JWT(JSON Web Token)是一个自包含,可签名额字符串,常用于鉴权 结构: 1HEADER.PAYLOAD.SIGNATURE HEADER:描述算法如HS256 Patload(Claims): 放自定义字段和标准字段,比如用户ID,过期时间,这个是外部可读的 Signature:对 header+payload 用密钥/私钥签名,保证不可篡改 AccessToken: 短期,用于日常访问,包含用户信息 RefreshToken: 长期,用于换新的accessToken,包含少量信息 JWT工作流程: 用户登录服务器,后端签发accessToken和refreshToken,前端保存token,每次访问接口时带上token,后端验证accessToken,通过则返回数据,如果accessToken过期了,前端自动使用RefreshToken获取新的accessToken,如果refreshToken也过期了,用户要重新登陆
go
思来想去,最后还是决定放弃java去写go了,一方面是java确实比较卷,卷王扎堆,但是更主要的还是自己不喜欢写java。 自己最早其实从7月的时候就有这个想法了,但是当时没有下定决心,而且当时在学cs61b,这门课使用java,所以当时的决定还是继续java,后面开学了开始学框架,看黑马写项目,结果越来越焦虑,经常写着写着就破防了,当时对java就很讨厌了,但是考虑到自己已经学了不少java的技术栈,有一个沉没成本的问题,还是硬着头皮写了一个月把苍穹外卖做了,最后痛苦越来越多,我对学习java已经没有任何兴趣,完全是焦虑驱动学习,在最后一次破防摆烂了几天后,决定转go,那天是11月8号,到现在9天,用了2天学了基础的语法,然后简单的了解了一些go的爬虫,就开始学gin和gorm,之后开始用框架错了一个简单的备忘录后端,这几天的感觉前所未有的好,只能说为什么不早点去学go
KMP算法
解决在主串中快速匹配子串的问题 传统暴力算法每次失败都要从头开始,时间复杂度是$$ O(m * n) $$,效率比较差 核心思想:利用已经匹配过的信息,避免主串指针回退,从而加速匹配 KMP是如何实现优化的呢? 前缀表 next[i] = 当 needle[0..i]不匹配时,应跳回的下一个可匹配位置(前缀长度) 假设我们匹配: 12345678910111213主串: ABC ABCDAB ABCDABCDABDE子串: ABCDABD当匹配到:ABCDAB **E**ABCDAB **D**在 E != D 时:暴力算法会回到开头: ABCDAB E-> A 但 KMP 会使用 next 数组得知: 已匹配的 “ABCDAB” 中前缀和后缀的最长相等部分是 “AB”(长度 2) 所以只需跳回到 needle[2] 继续匹配,而无须重来。 这大幅减少了重复比较。 为什么next数组可以帮助跳位置 因为next[i]表示的是以 i...
ubuntu挂载新分区
我使用的是windows11与ubuntu22.04双系统,当时装ubuntu的时候还是以windows做主力的,所以内存只分了100G,现在ubuntu使用的越来越多,windows好几天才启动一次,100G的空间有点不够用了,就想扩容一下 最开始还是想直接分到根目录下的,找了找教程,有点麻烦,而且有挺大的风险,于是就找了这个替代方案 从windows压缩空间: win + x进入磁盘管理,找到空闲空间比较大的盘,右键选择压缩卷,输入想要给ubuntu的空间大小 点击压缩,等待一会就可以看间出现了一块未分配的空间 在ubuntu上挂载: 打开disks,可以看见在windows创建出来的未分配空间, 点击下面的+创建新分区 创建分区时类型要选择Ext4 设置自动挂载 点击刚刚设置好得分区下面的齿轮图标,选择“编辑挂载选项”,关闭用户会话默认设置,勾选“在系统启动时挂载”,命名挂载点,确定 新挂载的分区默认只有root才能写入,所以要修改所有权 sudo mkdir 挂载点 sudo mount -a挂载新分区 sudo chown -R...
reset
前些天一直在学苍穹外卖,一开始只是因为redis的测试一直无法运行,就照着ai一顿瞎搞,最后成功的把代码弄乱了,想着reset到上次提交的版本吧,自己当时有点后悔为什么没有多commit几次,基本是3天的内容没了,不过也还好,但是的自己很快就接受了。自己对回滚的操作并不熟悉,就再次询问AI,再次相信了它,结果执行了clean命令,删除了一些文件,导致项目再次无法启动,当时以为这个项目彻底废了,直接破防,玩了两天别的东西,今天抢救一下,还好只是丢了一些修改,无伤大雅。 这次也是涨个教训吧,一定要多commit,还有就是不要无脑信ai的话,因为自己的描述可能有问题,它不了解实际场景。
docker
docker与虚拟机的区别 虚拟机是模拟硬件创建虚拟操作系统,运行多个虚拟机就是运行多个操作系统,docker还是使用宿主机的操作系统 容器与镜像 镜像是程序安装包,容器是运行中的程序,一个镜像可以run出多个容器 常用命令 12345678910111213#我们可以使用docker pull images#从仓库下载到本地,要启动镜像的容器输入`run`命令#查看当前容器列表docker ps -a#开启停止状态的容器docker start <容器名称/容器ID>#停止容器直接输入stop命令 docker stop <容器名称/容器ID>#如果我们不需要使用容器了,那么可以将容器删除,但是注意只有容器处于非运行状态时才可以删除:docker rm <容器名称/容器ID>#容器在停止后自动删除,我们可以在运行时添加--rm参数:docker run --rm 镜像名称 构建镜像 dockerfile FROM: 一个dockerfile必须以FROM指令开始 作用:指定基础镜像 COPY 作用:将你宿主机 (你电脑)...
dp完全背包.md
看代码随想录一直不太理解这两句话 如果求组合数就是外层for循环遍历物品,内层for遍历背包。 如果求排列数就是外层for遍历背包,内层for循环遍历物品。 为什么是这样? 12345678// 求组合数// 外层循环:遍历物品(颜料)for (int item : items) { // 内层循环:遍历背包容量(货架格子) for (int j = item; j <= capacity; j++) { dp[j] += dp[j - item]; }} 第一轮 (拿出红色颜料):你拿着红色颜料,从头到尾把货架上所有能刷的地方都刷一遍,更新一遍货架的状态。刷完后,你把红色颜料放回去,并且再也不碰它了。 第二轮 (拿出蓝色颜料):你拿着蓝色颜料,在当前已经有了红色的货架的基础上,再把所有能刷的地方刷一遍。因为你固定了物品的使用顺序。你总是先用完所有可能的红色,再用蓝色,再用绿色。所以,你最终得到的方案里,颜色出现的顺序必然是 (红, 蓝, 绿),你永远不会得到 (蓝, 红, 绿)...
spring快速入门1
今天搓了一个简单的博客后端,然后之后准备学spring,今天借助gemini和博客简单了解一下spring里面的概念 优秀的设计都致力于一件事,解耦 开闭原则(OCP Open/Closed principle) 软件实体应该对扩展开放,对修改关闭,简单来讲就是不改变已有的稳定代码,添加新功能 依赖倒置原则(DIP dependence inversion principle) 高层模块不应该依赖低层模块,两者都应该依赖于抽象(接口)。简单说就是:要面向接口编程,不要面向具体实现编程,想象一下电脑,电脑(高层模块)不关心你插进来的是U盘、鼠标还是键盘(低层模块/具体实现)。只要它们都符合USB接口规范,就能正常工作。 spring的8个模块 spring Core:核心容器,提供了Ioc和DI,负责管理spring中的bean spring Context:在core的基础上增加更多的功能 spring ADP:面向切面编程 spring DAO:数据访问对象 spring ORM:对象关系映射 spring Web MVC spring...
postgreSQL学习笔记(三)
聚合函数 对一组值进行计算,返回单个值,将多行数据压缩成一个统计结果 常用函数 COUNT(*):统计行数 SUM(colum) AVG(column):计算平均值 MAX(column) MIN(column) 12345-- 计算总员工数SELECT COUNT(*) FROM employees;-- 计算公司月薪总支出SELECT SUM(salary) FROM employees; GROUP BY子句 用于将数据按一列或多列进行分组 在SELECT语句中出现的列,并且没被聚合函数包裹都必须出现在GROUP BY子句中 12345678SELECT grouping_column, aggregate_function(column_to_aggregate)FROM table_nameGROUP BY grouping_column; 窗口函数 不改变原始行数,在每一行后面添加聚合计算结果 GROUP...

