跳到主要内容

一天零基础用Godot做了个游戏,随便写点

· 阅读需 8 分钟

前言

五一期间花了一天时间用Godot做了个游戏,想记录点什么。本来五一期间就该写这篇博客的,奈何本人有些拖延,拖着拖着就拖了半个月才想着写。再回看自己的博客,发现已有接近有一年没有写了,不知不觉时间过得真快,稍不留神竟然已经过了这么久了,想想真是有些惭愧。

其实我之前是从没听过Godot的,游戏引擎我之前只知道Unity、UE、Cocos、Pygame这些,不知什么时候横空出世的Godot。五一期间在刷B站时,我无意间刷到Unity又变更条款的消息,Unity6不让中国用了,中国只能用特供版,也就是团结引擎,特供版和国际版未来会独立发展。然后就了解到了开源游戏引擎Godot的存在,于是就想挑战自己一下,一天时间零基础用Godot做一个简单的游戏,结果基本上做到了。

记Chrome浏览器BUG导致csv上传失败问题排查

· 阅读需 5 分钟

最近有业务反馈有个系统上传csv总是失败,提示“文件只能为csv格式,请重新上传”:

上传失败截图

但是,我在自己电脑上测试了多次都能正常上传。心想,这难道就是传说中的,不是代码的问题,而是用户电脑环境的问题吗? 于是,我与该业务会议沟通,通过查浏览器开发者工具中的网络记录,发现业务的电脑在上传时并没有发送上传请求就被拦截上传失败了。很显然,这应该是前端的问题。前端使用了Vue+elementUI,代码逻辑大概如下:

《go语言趣学指南》学习笔记

· 阅读需 9 分钟

命令式编程

格式化输出

  • %v :默认格式打印
  • %b :以二进制格式打印整数
  • %f :浮点数打印。%05.2f 表示宽度为5,精度为2,前面补0。
  • %c :打印Unicode字符
  • %s :以字符串打印
  • %[1]v :以默认格式打印第1个参数。参数索引以1开始。

循环和分支

// if语句
if 条件1 {
} else if 条件2 {
} else {
}

// switch语句
switch 变量 {
case1: 表达式1
case2: 表达式2
default: 表达式3
// switch语句不需要加break,默认不执行下一分支的代码
// 如果要执行下一分支的代码,使用 fallthrough 关键字

// 循环
for 条件 {
}
for i := 0; i < 10; i++ {
}

缓存的常见套路

· 阅读需 26 分钟

缓存的几种模式

在高并发场景下,缓存在数据库前面挡住了大量的查询流量,减轻了数据库的压力。对于缓存的更新,通常有以下几种模式:

模式优点缺点
Cache Aside1. 实现简单1. 需要调用方维护缓存和数据库的更新逻
2. 代码侵入性大
Read/Write Through1. 引入缓存管理组件,缓存和数据库的维护对应用方是透明的
2. 应用代码侵入性小,逻辑清洗
1. 引入缓存管理组件,实现复杂
Write Behind Caching1. 读写直接与缓存打交道,异步批量更新数据库,性能最好
2. 缓存和数据库的维护对应用方是透明的
1. 实现最复杂
2. 存在数据丢失风险
3. 一致性最弱

Cache Aside Pattern

这种模式应用最为广泛,其逻辑如下:

  • 读过程:先读缓存,若命中则返回;否则从数据库中查询数据,写入缓存并返回
  • 写过程:先更新数据库,然后让缓存失效

谷歌Guava限流器的设计与实现

· 阅读需 10 分钟

介绍

谷歌Guava工具包提供了一个单机限流工具,它基于令牌桶算法实现,主要被用于限制访问资源的速度。

Guava限流器的简单使用例子:

// 每秒2个令牌
RateLimiter rateLimiter = RateLimiter.create(2);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
TimeUnit.SECONDS.sleep(1);
for (int i = 0; i < 10; i++) {
// 阻塞式获取1个令牌
rateLimiter.acquire(1);
System.out.println(LocalDateTime.now().format(dateTimeFormatter));
}

其输出如下:

23:49:48.131
23:49:48.132
23:49:48.132
23:49:48.628
23:49:49.127
23:49:49.627
23:49:50.128
23:49:50.628
23:49:51.128
23:49:51.627