All Posts

Httprouter介绍及源码阅读

在上一篇文章当中阅读了Go语言的一个高性能的Web框架Gin,Web框架当中最重要的功能之一是路由,Gin的路由就是由httprouter这个包实现的 地址 https://github.com/julienschmidt/httprouter https://godoc.org/github.com/julienschmidt/httprouter 特性 基于基数树实现的高性能路由框架 仅支持精确匹配 不必关心URL结尾的斜线 路径自动校正,例如在url路径当中有../,//的时候 可以在URL当中设置参数,例如/user/:id 零内存分配 不存在服务器崩溃,可以通过设置panic handler使服务器从panic当中恢复 适合API构建 源码 两个问题 解决两个问题,就基本明白了这个路由框架 路由是是如何注册?如何保存的? 当请求到来之后,路由是如何匹配,如何查找的? 一个Demo 还是从一个Hello World讲起 func main() { r := httprouter.New() r.GET("/:name", func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) { fmt.Fprintf(writer, "hello, %s!\n", params.ByName("name")) }) http.ListenAndServe(":8080",r) } httprouter.New()初始化了一个Router,下面直接看一下Router的结构 Router 在Router的源码当中有十分详尽的注释,这里按照我个人的理解注释一下 // Router实现了Http.Handler接口,用于注册分发路由 type Router struct { // trees 是一个基数树集合,每一个HTTP方法对应一棵单独的路由树 // node是基数树的根节点 trees map[string]*node // 用于开启上文提到的自动处理URL尾部斜杆的特性 // 这个值为true时,如果/foo/没有被匹配到,会尝试匹配/foo RedirectTrailingSlash bool // 用于开启上文提到的路由校正的特性 // 这个值为true时,会对.

Gin源码阅读 从0.1开始

最近打算开始学习一下Gin的源代码,现在Gin已经是一个十分成熟的框架了,代码量也不少,阅读起来还是有一定的难度,所以我打算从0.1版本开始阅读学习,一直到最新的一个版本。跟随着Gin的源码一步一步的学习成长。 目录结构 Gin 0.1的代码量十分的少, 主要代码一共也只有五个文件,代码中的注释也比较详细 │ auth.go │ gin.go │ logger.go │ README.md │ recovery.go │ validation.go 跑起来 Gin 0.1的代码量十分的少,但是还是先从readme的示例开始说起 首先下面这一段代码是直接跑不起来的,不知道是代码本身的bug还是因为Go语言的版本变化导致的,首先我们需要修改几个地方 import "github.com/gin-gonic/gin" func main() { r := gin.Default() r.GET("ping", func(c *gin.Context){ c.String("pong") }) // Listen and server on 0.0.0.0:8080 r.Run(":80") } 第一次修改 main.go package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { r := gin.Default() // 在这儿必须在ping,前加上/,不然会导致panic r.GET("/ping", func(c *gin.Context){ // String 方法接受两个参数,但是实例只写了一个 c.

纯技术人员和投资者的一些区别

以下都是流水账,感慨一下… 今天有幸参加了一位师兄的校友聚会,也很巧合,和很多大佬一起吃了一个饭,听大佬们聊天受益颇多。 今天有一位做技术很厉害的,专家级的师兄想创业,聊起了他的项目,另外几个做企业的师兄在旁边听并且给出建议。让我产生一种很强烈的对比,做技术的师兄考虑的最多的是技术十分的牛,技术拥有不可复制,或者说很高的复制成本。但是没有说到具体的牛在什么地方,而其他几个师兄在帮忙理清项目的思路,有没有做过市场调查,有没有成型的产品,产品具体的技术指标等等。 不同位置的人看问题的角度不一样,或许只有那个技术很牛的师兄一样才能把一门技术做到极致。 但是反过来思考一下做技术需不需要有一定的产品思维,需不需要了解市场动态,需不需要良好的一个语言表述和组织能力,虽然这些肯定不是最重要的,但是应该也是不可或缺的吧。 自勉

2018年的一些小目标

时间过得很快,从一个学生到一个社会人只需要那么一瞬间,一个来不及反应的瞬间。虽然之前经历过大量的实习工作,也不是第一次只身一人千里迢迢来到这个陌生的城市,但是还是有那么一些的不适应。 开始工作了,时间变得少了,但是学习的紧迫性却是变得更高了 列一列剩下不到半年时间想要学习的东西吧,权当是一个备忘录 阅读学习至少两个Go Web框架 七八月 Echo Gin Iris Beego … 学习Golang调度源码 七八月 or 九月 从零开始编写自己的第一个Go Web框架 八九月 未完待续… 希望能够养成记录学习过程的习惯,好记性不如烂笔头

go标准库——ioutil.ReadAll的实现

序 最近准备学习一下golang的标准库,详细的阅读部分源码,这个目录记录一下学习的过程和心得 go语言的ioutil包提供了很多方便的io操作的工具集,本文主要详细分析ReadAll方法的源码实现。 ReadAll是很常用的一个方法,用来一次性的读取io.Reader当中的数据。 源码实现 1. ReadAll 阅读下方的源码我们可以发现,ReadAll其实调用了一个非导出的方法,我们一步一步的追踪 // ReadAll reads from r until an error or EOF and returns the data it read. // A successful call returns err == nil, not err == EOF. Because ReadAll is // defined to read from src until EOF, it does not treat an EOF from Read // as an error to be reported. // ReadAll从r读取数据直到EOF或遇到error,返回读取的数据和遇到的错误。 // 成功的调用返回的err为nil而非EOF。 // 因为本函数定义为读取r直到EOF,它不会将读取返回的EOF视为应报告的错误。 func ReadAll(r io.

使用chromedp解决反爬虫问题

前言 最近We川大上的教务处公告新闻已经很久没有更新了,想到可能是ip被封了,查了一下log,发现并不是,而是获取到的页面全变成了混淆过的js,下面放两个格式化的函数 function _$Es(_$Cu) { _$Cu[14] = _$v9(); _$Cu[_$yf(_$ox(), 16)] = _$Dn(); var _$cR = _$CR(); _$cR = _$iT(); return _$DA(); } function _$Dk(_$Cu) { var _$x5 = _$Dv(); var _$x5 = _$EB(); if (_$Ex()) { _$w9 = _$Dw(); } _$Cu[_$yf(_$EJ(), 16)] = _$ED(); _$Cu[_$yf(_$Ep(), 16)] = _$EP(); _$w9 = _$EB(); return _$Cu[_$yf(_$v9(), 16)]; } function _$rK() { var _$aJ = _$c0(_$DN()); _$aJ = _$BC(_$aJ, 2); var _$Ce = _$yr(_$qt()); for (var _$Cu = 0; _$Cu < _$aJ[_$gX()]; _$Cu++) { _$aJ[_$Cu] = _$Ce + _$aJ[_$Cu]; } return _$aJ; } 看着这一堆就头大,但是本着只要是浏览器能够渲染出来的页面爬虫就可以爬到的原则,一步一步的解决

We川大开发笔记@0.2.0

序 可以搜索小程序we川大直接体验 这不是刚刚发完0.1.0的笔记么?怎么0.2.0都出来了? 没有看错,效率就是那么高,上一篇也提到了0.1.0审核通过的时候0.2.0就基本已经完成了,而且现在已经上线了(准确的说是0.2.1版本),这一次的审核快了许多,只用了不到两天就已经审核通过了 功能预览 这一版主要新增三个功能,然后就是一些优化: 1.反馈 参考we重邮,直接和github的issue关联,所有提交的反馈信息,都会新建一条issue,为了防止滥用,每天的反馈次数做了一定的限制 这个后端上直接采用了Google的go-github包,开发起来十分的方便,只是文档资料不是特别的丰富,之后会专门总结一下 2.空闲教室查询 学校的空闲教室查询页面:http://cir.scu.edu.cn/cir/index.html 这是学校难得做的比较友好的站点,对于这个需要后端做一次接口中转即可 3.新闻Tag列表 这一版可以直接通过点击列表的tag,查看前20条包含该tag的新闻, 至于为什么是20条,因为一个很奇怪的bug现在还没有解决。 两个页面,A,B包含了同一个模块C,在模块C当中可以点击跳转到B,现在的问题就是在A页面的C模块当中点击跳转到B页面之后,B页面的C模块的scroll-view绑定的所有事件都会消失 图片预览 博客原文&&开源地址 https://github.com/mohuishou/scuplus-wechat http://lailin.xyz/post/We川大开发笔记@0.2.0/ 可以关注开发进度或者提交反馈或者是PR,star多多益善

We川大开发笔记@0.1.0

序 微信小程序已经出来一年左右了,然后之前也写过一个scuplus的web项目,但是还没有正式上线就无疾而终了,当然也不是一点用处都没有,拆分出来了两个小的功能模块,一个是绩点计算器,一个快捷评教,绩点计算器的日PV快要破3W了,UV已经破1W了,大家期末看成绩的心情依旧是那么的急迫。 按理来说,我即将毕业做这些其实不太好,毕业之后代码的维护以及运营都是一个大问题,但是川大一直缺少一个综合型的APP或者网站,学校官方的网站做的都及其的不友好,而且十分的分散,所以一直有这个想法,想做一个集新闻资讯、比赛资讯/找队友/拉票,教务查询,课程推荐/排名/评价/选课,书籍查询/借阅于一体的一个综合型网站。当然这个想法涉及到的东西有点多,吸取之前的教训,这次打算一步一步的来,前期做功能,后期做优化,分模块上线 使用微信小程序开发好处是不用考虑浏览器的兼容性也不用考虑去做两个APP,以及各种型号的手机,但是不好的地方就是所有的界面都只能靠自己去实现,基本没有现成的ui框架,有时候写的有点蛋疼(PS我是一个后端)。然后就是审核,微信的审核0.1.0版本用了5天才完成,这个时间我的0.2.0版本已经基本开发完成了 项目已经开源,可以关注开发进度或者提交反馈或者是PR,star多多益善 https://github.com/mohuishou/scuplus-wechat 扫码体验 功能预览 0.1.0 版本只是完成了基本的框架,以及相对来说比较常用的功能: 最新资讯(青春川大/scuinfo/教务处/学工部等) 成绩/GPA查询 课表查询 图片预览

招银网络面试总结

三面同时进行,每一面间隔不超过五分钟,前面两面技术面最后一面HR,完全不会JAVA,结果一直问JAVA心态爆炸 一面(20min) 1. 自我介绍 2. JAVA用过么?准备去什么地方? 用过一天写了一个小APP 3. JAVA的HashMap怎么实现?PUT一次做了什么操作 不会 4. JAVA的GC怎么实现 不会,强行说了一波PHP的GC 5. Mysql的锁 Innodb支持到行级锁,MyISAM只支持到表 6. 求一个二叉树任意两节点的距离,时间复杂度是多少? 7. 设计模式了解不?装饰器模式解释一下,写一个 解释了一下,没有写,后面让写了一个工厂 > 还有一些忘了 二面(15min) 1. 自我介绍 2. JAVA的GC怎么实现。。。又来了 3. Mysql去除重复项 4. Mysql触发器机制 5. 设计一个无限极分类的数据库表 6. 怎么把去处来的数据树型结构化 三面(35min) 1. 拿了一波简历,成绩单,自我介绍 2. 为什么不想留在成都 3. 成绩单上很多60分,飘过还是重修 飘过 4. 现在面试了哪些公司,有没有收到offer意向 5. 简单的介绍了一个项目 6. 介绍了社团研发部部长和学院团副经历 还有一些记不住了

shell排序

Shell排序 说明 希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。 步骤 设置间隔(传统间隔为N/2) 插入排序 图片示例 程序示例 传统实现 //SortInt 传统shell排序,间隔为N/2 //相邻间隔可能不互质,可能会出现前置排序无用的情况 func SortInt(a []int) ([]int, int) { n := 0 aLen := len(a) //定义间隔 for i := aLen / 2; i > 0; i = i / 2 { //插入排序 for j := i; j < aLen; j++ { tmp := a[j] k := j for ; k >= i && tmp < a[k-i]; k = k - i { a[k] = a[k-i] n++ } a[k] = tmp } } return a, n } Hibbard算法 //SortHibbardInt Hibbard算法,间隔为2^k-1 func SortHibbardInt(a []int) ([]int, int) { n, i := 0, 0 aLen := len(a) for i = 1; i <= aLen-1; i = i*2 + 1 { } //定义间隔 for ; i > 0; i = (i - 1) / 2 { // println(i) //插入排序 for j := i; j < aLen; j++ { tmp := a[j] k := j for ; k >= i && tmp < a[k-i]; k = k - i { a[k] = a[k-i] n++ } a[k] = tmp } } return a, n }