@闲淡酱 QQ图片20201116024302.gif
-
Nginx,go,git,gogs这些软件安装都没遇到困难(倒不如说除了gogs其他早都安装过了),然后开始部署
特性支持太少,不支持GnuPG公钥验证 clone url为大小写敏感的用户名,但文件系统自动生成的是全小写的用户名目录,导致必须用gogs自带的终端,否则会报错仓库不存在 不支持插件,缺乏扩展性
为了性能(以及装逼),没有使用MySQL做数据库,而是选择了PostgreSQL,结果无论是gogs还是其他机器的psql都无法连接数据库。
开始排查,发现PostgreSQL监听的是127.0.0.1,改成0.0.0.0后psql能用管理员登录了,但是没法用gogs账号登录,因为PostgreSQL新建用户的默认密码为空,空密码不能用来登录。
于是改密码改完密码发现gogs还是连不上数据库,排查几小时都没找到原因,后来总算找到了一个PostgreSQL的样例,发现PostgreSQL链接前缀是postgres://,并不是postgresql://,我TM……
然后总算连上数据库了,反向代理后访问web界面,注册登陆,感觉亮色不适合我,下载了一个Dark Theme,结果代码高亮巨丑,一步一步改css改了几个小时
然后,现在还存在一些问题,例如早知道坑这么多我就去用GitLab了,现在好不容易搭好,懒得改了
-
-
-
-
-
-
回复: 推荐一下我的vim配置
Bruce Kang/vimrc
Release里有.vimrc和.vim文件夹的打包,网不好的可以直接下载下来,解压到/home/[your name]使用。 -
前言:因为最近Go很火,我之前关注的一个编辑器也是用Go写的,所以我打算自学一下Go语言
// 之前写C++比较多,不保证代码规范符合Go的标准 type foo struct { } func (f foo) method(params types) (returns) { // function body } func main() { bar := new(foo) params := "blabla" bar.method(params) }
结果,我发现Go完全没有某些人吹嘘的那么好,OOP部分无论是实现方式还是代码体验简直就是一坨翔,写起来甚至和C有点像。
定义方法其实就是定义函数,只不过函数的第一个参数是结构体(Go中甚至没有类的概念),和C函数唯一的区别就是把结构体参数提前到函数名前了:至于继承,直接把父结构嵌套在子结构中就算继承了:
type parent struct {} type child struct { parent }接口的继承也是嵌套,而接口的实现居然是靠赋值,并且官方工具目前好像还不支持静态检查:
type i interface { foo() } type s struce {} func (bar s) foo() {} func main() { a := s{} var b i = a b.foo() }写了半天,我还以为我回到了上个世纪写C的年代。恕我直言,C++的OOP做的都比Go好!
-
体验了大约一周,已经能达到20词/分的龟速了...中排键位已经记住了
Programmer Dvorak没试过,用的是Dvorak标准版,布局如下
dvorak.jpg
这几天用下来的感觉就是,右手小拇指累出天际了!虽然编程常用的"',.<>分布在了左手区上排,:;分布在了左手小拇指下排,但是右手区分布对程序员来说却极不合理
html需要经常用的连字符-,编程需要经常用的等号加减号下划线=+-_,斜杠反斜杠/\,撤回需要按的z,全部需要用右手小拇指按,并且需要移动,有的甚至还需要长距离移动。尤其是=,绝对是编程最常用的符号。
刚才打了200行代码,现在小拇指疼得不行。刚才看了下Programmer Dvorak,=在数字键6的位置说实话也不是很舒服,而且字母区保持了普通版dvorak的布局我认为是一个败笔。显然,程序员的字母输入频率是和打字员不一样的,但是function的f和c,new的w,main的mversion的v,json的j,return的r,都没有分布在中排,有的甚至分布在很难按到的位置。
综上所述,我认为Dvorak布局被过誉了,至少对于程序员来说,它并不算好用
-
最终效果图:
0. 安装vim
QQ截图20200912163204.jpg
一入vim深似海 从此gui是路人想要配置vim,首先肯定需要有vim这个软件。
Windows (gvim)
鉴于vim的强大和高效,很多系统都支持他,例如Windows,Mac OS,Linux,甚至OpenWrt。
安装方法也很简单下载安装包安装
或者,直接通过win-get也可以进行安装
winget install vim Mac OS略(我没用过Mac,但是听说有些Mac程序员也喜欢用vim,所以明显Mac也是支持的)
Linux一般发行版的仓库都会内置vim,直接用软件包管理程序安装即可
Debian系 sudo apt install vim RH系 sudo yum install vim 1. 安装并配置VundleVundle是一款用来管理vim插件的插件,而且可以通过git更新插件
1.1 安装git和安装vim的方法一样,例如Debian系可以通过sudo apt install git来进行安装
1.2 下载Vundle通过git进行克隆
git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim 1.3 配置插件首先,需要将以下配置加入~/.vimrc开头
set nocompatible " be iMproved, required filetype off " required " set the runtime path to include Vundle and initialize set rtp+=~/.vim/bundle/Vundle.vim call vundle#begin() " alternatively, pass a path where Vundle should install plugins "call vundle#begin('~/some/path/here') " let Vundle manage Vundle, required Plugin 'VundleVim/Vundle.vim' " The following are examples of different formats supported. " Keep Plugin commands between vundle#begin/end. " plugin on GitHub repo Plugin 'tpope/vim-fugitive' " plugin from http://vim-scripts.org/vim/scripts.html " Plugin 'L9' " Git plugin not hosted on GitHub Plugin 'git://git.wincent.com/command-t.git' " git repos on your local machine (i.e. when working on your own plugin) Plugin 'file:///home/gmarik/path/to/plugin' " The sparkup vim script is in a subdirectory of this repo called vim. " Pass the path to set the runtimepath properly. Plugin 'rstacruz/sparkup', {'rtp': 'vim/'} " Install L9 and avoid a Naming conflict if you've already installed a " different version somewhere else. " Plugin 'ascenator/L9', {'name': 'newL9'} " All of your Plugins must be added before the following line call vundle#end() " required filetype plugin indent on " required " To ignore plugin indent changes, instead use: "filetype plugin on " " Brief help " :PluginList - lists configured plugins " :PluginInstall - installs plugins; append `!` to update or just :PluginUpdate " :PluginSearch foo - searches for foo; append `!` to refresh local cache " :PluginClean - confirms removal of unused plugins; append `!` to auto-approve removal " " see :h vundle for more details or wiki for FAQ " Put your non-Plugin stuff after this line之后,就可以在call vundle#begin()和call vundle#end()之间添加你想安装的插件了
1.4 插件安装 vim +PluginInstall +qall *1.5 编译安装YouCompleteMe python3 ~/.vim/bundle/YouCompleteMe/install.py --all python3 ~/.vim/bundle/YouCompleteMe/install.py --clangd-completer *1.6 配置YouCompleteMe
这里推荐2个插件。valloric/YouCompleteMe,可以用来代码补全。tomassiser/vim-code-dark,vscode的暗色主题在.vimrc文件后面追加内容:
let g:ycm_key_invoke_completion = '<c-z>' set completeopt=menu,menuone let g:ycm_add_preview_to_completeopt = 0可以将语义补全的快捷键修改为Ctrl + z,默认的Ctrl + space是切换输入法。
2. 配置主题 set t_Co=256 " 需要终端支持256色 set t_ut= colorsheme codedark 3. 配置状态栏 3.1 状态栏常驻显示 set laststatus=2 3.2 获取git branch function! GitBranch() return system("git rev-parse --abbrev-ref HEAD 2>/dev/null | tr -d '\n'") endfunction function! GetBranch() let l:branchname = GitBranch() return strlen(l:branchname) > 0? ' '.l:branchname.' ': '' endfunction 3.3 自定义状态栏 set statusline= set statusline+=%#PmenuSel# set statusline+=%{GetBranch()} set statusline+=%#LineNr# set statusline+=\ %F set statusline+=%m set statusline+=%= set statusline+=%#CursorColumn# set statusline+=\ %y set statusline+=\ %{&fileencoding?&fileencoding:&encoding} set statusline+=[%{&fileformat}] set statusline+=\ %p%% set statusline+=\ %l:%c
可以在切换补全的时候禁用函数原型展示,避免扰乱布局显示出来的效果是 branch - 路径 - 类型 - 编码 - 行尾 - 百分比 - 行:列
3.4 行号等杂项 set nowrap " 取消自动折行 set tabstop=8 softtabstop=0 expandtab shiftwidth=4 smarttab " 将tab键切换为4个空格 set nu " 显示行号 set smartindent " 智能缩进 set mouse=a " 支持鼠标 set cursorline " 高亮当前行 set cc=81 " 高亮第81列(在行长度超过80时起到提示作用,避免写出不便阅读的代码) 4. 配置符号配对其实思路就是将一个按键映射成多个按键
inoremap ' ''<ESC>i inoremap " ""<ESC>i inoremap ( ()<ESC>i inoremap [ []<ESC>i inoremap ` ``<ESC>i inoremap { {}<ESC>i不建议配置尖括号的配对,尖括号只有在泛型和C/C++引入头文件时才需要配对,这种场合相对来说较少。
但是,当你写代码需要用到小于号时,你就会发现你配置的尖括号补全有多艹蛋了... -
逻辑崩坏,作画崩坏,剧情崩坏,总之,能崩的他都崩了
第一话 被毒针刺中后大约5小时变成GIBIA,但是毒素要24小时才能进入人体,5 > 24? 疫苗可以治疗疾病,高中生物老师哭晕在厕所 第二话 一个剑道初级到底是有多瞧不起古人,要和千人斩比试剑术? 前田自告奋勇去取刀,结果带回来的时候这么唯唯诺诺,他看到武士直接高潮行动都不考虑后果的吗? 防卫部队也不检查前田是否被感染,直接放他进来? 这么大的基地连备用发电系统都没有吗? 前田送刀的时候和神崎千水互相对望了那么久,GIBIA来的时候两人还站在原地,集体掉线? 上一集说要5小时才能变成GIBIA,这一集15:02被刺就直接变了?这番的逻辑就尼玛离谱,感觉就像给我喂了2吨屎
-
最近在学微服务,学到Eureka注册中心的安全验证这一节时,按照文档的说法,先添加了spring-boot-starter-security依赖,然后在配置文件中设置了账号密码,并添加配置类用来忽略服务注册时的CSRF验证
package org.bkcloud.config; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().ignoringAntMatchers("/eureka/**"); super.configure(http); } }然后,当我的服务用账号密码注册到注册中心时,却提示
com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
我花了几个小时各种改配置 ,重新启动,仍然无法解决。我甚至尝试过直接禁用CSRF防护,也没有效果。
总结
最终,我重启IDE,重新运行程序,问题莫名其妙就解决了此次问题
原因:未知 解决方法:未知 感想:一脸懵逼 -
-
前因是Eclipse Foundation与Oracle谈判破裂,因此Eclipse Foundation与Jakarta EE社区不再能使用javax.*包空间,因此代码必须做出改变,把javax.*下的内容迁移到jakarta.*(Oracle法务部牛逼)
然后,Tomcat 10,2020年2月开始测试,使用的是新的包空间,因此几乎所有涉及到Java代码的web应用都需要做出更改,SpringFramework也不能幸免
java.lang.IllegalStateException: Failed to load ApplicationContext Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.bkcloud.HelloMVCApplication]; nested exception is java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.boot.web.servlet.support.SpringBootServletInitializer Caused by: java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.boot.web.servlet.support.SpringBootServletInitializer Caused by: java.lang.IllegalStateException: Failed to introspect Class [org.springframework.boot.web.servlet.support.SpringBootServletInitializer] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@15db9742] Caused by: java.lang.NoClassDefFoundError: javax/servlet/ServletContext Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContext
刚才我去Tomcat官网下载了10.0.0-M5版本并把我部署在Tomcat 9上的SpringBoot应用部署到上面,果然在启动阶段就直接报错了:Tomcat 10提供了官方的迁移工具,可以把9的项目迁移到10,但是需要从GitHub下载源码,自己编译,而且版本号居然是0.0.1
总之,目前完全没动力从9迁移到10,还是等Spring和Tomcat适配完毕再考虑吧,我还是比较喜欢无痛迁移 -
用C++写了个调用Python脚本的功能,代码和Python官方文档上的Embedding Python in Another Application部分差不多,结果在Py_Initialize()处无限崩溃,头文件库文件动态链接库什么的都添加好了,但就是崩溃
后来我在其他地方找到了这么一句话On Windows, the (non-source) Python Windows installer can be used. Make sure that you use the same compiler as the one that your Python distribution is built with.
总之就是,你的项目和Python的编译器必须相同,而我的Python用的是MSVC,项目用的是MinGW
我打开VS,复制黏贴一气呵成,编译运行,成功淦...这尼玛是天坑啊,MinGW和MSVC的二进制文件居然不兼容,浪费了老子一晚上的时间
-
需要统计一个精确到1ms的时间
一开始我用的是QTimer类,间隔1ms让一个整形量自增1,结果发现QTimer效率还是太低,虽然可以精确到毫秒,但是没法准确控制间隔为1ms,具体来说平均间隔大约为1.2ms。
不过后来我发现这个量没必要由我自己去维护,Qt内置了QElapsedTimer类,专门用来计时,可以精确到μs,使用elapsed()方法直接获取start()开始计时后经过的毫秒数。最终测试结果确实比较准确,平均间隔可以达到1.0ms。
不过我录了一个120FPS的视频逐帧分析后发现,这个读数的尾数浮动其实非常大,理论上120FPS的视频每帧间隔是8.33ms,但是用elapsed()方法获取到的整形值的间隔却是4-11,浮动高达大约50%。理论上可以精确到μs的计时器不可能在ms数量级上产生这么大的误差啊...
虽然有可能是GUI绘制耗时产生的误差,但是原来使用QTimer时也没遇到这么大的误差。显示当前经过毫秒的源代码如下
#include "msecsgetter.h" #include "ui_msecsgetter.h" #include <QDateTime> //定义重绘GUI的间隔,单位ms #define INTERVAL 4 MSecsGetter::MSecsGetter(QWidget *parent) : QWidget(parent) , ui(new Ui::MSecsGetter) { ui->setupUi(this); timer = new QTimer(this); //定时器,用来定时触发重绘GUI tick = new QElapsedTimer(); //计时器,用来记录经过的毫秒数 //当计时器完成一次计时后,将GUI上的label内数字重绘为当前经过的毫秒数 connect(timer, &QTimer::timeout, [=]() { ui->label->setText(QString::number(startTime + tick->elapsed())); }); startTime = QDateTime::currentMSecsSinceEpoch(); //以自1970-01-01 00:00:00经过的毫秒数为初值 //启动定时器和计时器 tick->start(); timer->start(INTERVAL); } MSecsGetter::~MSecsGetter() { delete ui; }后续:找到问题原因了,GUI重绘间隔的问题,把间隔调成1就好了,不过因为GUI重绘比较耗时(至少比让一个整形自增费时),所以会有约1ms的误差
-
前言:在Google Play上下载了一个数独小游戏,玩了几把之后开始思考怎么利用程序解数独。
Class Sodoku { public: Sodoku(); //默认构造函数 Sodoku(const Sodoku &sodoku); //根据给定的已经填充一部分的数独生成一个数独实例的构造函数 ~Soduku(); //析构函数 private: std::vector< std::vector<Cell> >; //用来存放数独的81个格子,不使用int表示是因为高难度数独中每个格子的状态难以确定,需要添加一些标注辅助解谜 std::priority_queue<Cell>; //优先级队列,用来根据每个格子被解出的预期存放格子,并在解谜算法中进行遍历 protected: void run(); //用来开启一个新线程,高难度数独解起来很慢,所以最好采取多线程的方式进行处理 void deal(Cell c); //用来遍历优先级队列并更改格子状态的函数,解谜算法的重点 void insert(Cell c, int n); //将数字插入格子的算法 void mark(Cell c, int n); //对格子进行标注的算法,解答高难度数独时需要用到 void remove_from_queue(Cell c); //当一个格子状态被确定后(即填入数字后),将格子从优先级队列中移除的算法 //可能还有其他必需的成员函数或成员,用来辅助解答 }
感觉用程序算法来实现还是挺复杂的。
首先要把9*9的数独矩阵表示出来,需要在数独类中维护一个9*9的二维向量,每个九宫格用一个含有9个Cell实例的向量存放,并且提供一个优先级队列,用来存放数独的计算任务,以及提供一些进行操作的接口表示单个格子的Cell类,至少需要存放这个格子填入的数字,这个格子的标注,以及这个格子的状态(是否被遍历等)
Class Cell { public: Cell(); //默认构造函数 Cell(int n); //根据数字直接构造出一个填好数字的单元格 ~Cell(); //析构函数 private: int digit; //表示填入这个格子的数字 bool is_visit; //表示该格子是否已被遍历 std::list<int> marks; //表示当前格子被标注的数字,解答高难度数独时起到辅助解答的作用 //可能还需要其他成员、方法来辅助解答 }之后,剩下的就是利用排除法等解答数独的方法实现具体的接口了,不过我能力和时间有限,暂时就不写具体实现了
总体来说,解答数独本身算法实现已经较难了,如果想高效实现,估计需要相当好的逻辑思维以及算法和数据结构知识 -
想进入互联网行业写代码,但是本科专业不是计算机相关的
不想写前端,虽然基础我也会,但是我对做界面没那么感兴趣,我还是更喜欢写各种底层逻辑以及交互,也就是后端
Java会一些,但是感觉条条框框太多了,写个项目的配置文件都要研究半天,不如C/C++灵活高效
目前用的最多的就是Python和C++,而且对于个人团队来说,Python写后端,前端用html瞎写一点,C++用来开发客户端,足够了
然而企业好像不这么想,首先招聘要求就有计算机相关专业,其次基本清一色的招Java程序员,C/C++倒是有,但是基本都是架构工程师之类的职位,还要求几年的工作经验。Python就更少了,目前本地只看到一个算法开发工程师要求Python的
不知道是不是因为我这2线小城市对互联网的需求也就这些
不过我真的很喜欢Python和C++,想靠他们吃饭 -
李白
海客谈瀛洲,烟涛微茫信难求;
越人语天姥,云霞明灭或可睹。
天姥连天向天横,势拔五岳掩赤城。
天台四万八千丈,对此欲倒东南倾。
我欲因之梦吴越,一夜飞度镜湖月。
湖月照我影,送我至剡溪。
谢公宿处今尚在,渌水荡漾清猿啼。
脚著谢公屐,身登青云梯。
半壁见海日,空中闻天鸡。
千岩万转路不定,迷花倚石忽已暝。
熊咆龙吟殷岩泉,栗深林兮惊层巅。
云青青兮欲雨,水澹澹兮生烟。
列缺霹雳,丘峦崩摧。
洞天石扉,訇然中开。
青冥浩荡不见底,日月照耀金银台。
霓为衣兮风为马,云之君兮纷纷而来下。
虎鼓瑟兮鸾回车,仙之人兮列如麻。
忽魂悸以魄动,恍惊起而长嗟。
惟觉时之枕席,失向来之烟霞。
世间行乐亦如此,古来万事东流水。
别君去兮何时还?且放白鹿青崖间。须行即骑访名山。
安能摧眉折腰事权贵,使我不得开心颜!