冬天好冷啊
2014-12-27 00:00
好吧其实也算不上一年的
因为中途从Firefox换到了Chrome(谁让Flash不支持了嘛),然后导入的记录没有浏览次数记录
A:admin.XXXX.net -保密
B:bilibili.com -这个就不用解释了
C:coding.net -国内一个代码托管平台,做的还不错
D:dartlang.cc -dart的非官方中文站,学dart的时候经常打开
E:extensions.gnome.org -GNOME的插件网站,折腾插件的时候用的
F:fontawesome.io -写网页找图标时翻的
G:github.com -最近开的坑又变多了
H:html5up.net -写网页找模板用
I:inbox.google.com -不用解释
J:jandan.net -煎蛋偶尔看看
K:kde-look.org -找kde主题
L:linuxdeepin.com -作为版主还是需要经常看看的
M:minecraft.net -Minecraft官网,经常改皮肤
N:neovim.org -号称21世纪的vim?不过我一直没编译成功带GUI的
O:origin.com -钱钱钱
P:pan.baidu.com -国内传文件
Q:qaq.gd -某只熊猫的博客
R:没有
S:solidot.org -资讯平台
T:twitter.com -……
U:还是没有
V:v2ex.com -签到签到
W:wiki.archlinux.org -arch万能的wiki
X:xshellz.com -一个免费VPS,不过好久没用过了
Y:youtube.com -HTML5播放器好赞
Z:zybuluo.com -在线MarkDown编辑器,相当强大
语法强迫症
2014-11-21 00:00
在群里讨论到了这个问题
然后下面这是官方给出的例子
var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
fmt.Printf("unexpected type %T", t) // %T prints whatever type t has
case bool:
fmt.Printf("boolean %t\n", t) // t has type bool
case int:
fmt.Printf("integer %d\n", t) // t has type int
case *bool:
fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}
里面有几点要注意一下
在switch t := t.(type)
时
switch
的其实是t.(type)
而不是被创建的t
然后t := t.(type)
创建的是类型为t.(type)
,值为t
的值的一个变量
里面所使用的t
都是switch
里新建的那个t
等于下面这个例子
var t interface{}
t = functionOfSomeType()
switch t.(type) {
default:
fmt.Printf("unexpected type %T", t) // %T prints whatever type t has
case bool:
t := t.(bool)
fmt.Printf("boolean %t\n", t) // t has type bool
case int:
t := t.(int)
fmt.Printf("integer %d\n", t) // t has type int
case *bool:
t := t.(*bool)
fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
t := t.(*int)
fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}
瞬间高大上
2014-11-07 00:00
除了50行的custom.css和几行html修改之外全部都是直接找的模板哇咔咔
虽然上上上次说要重新写一个静态博客生成工具,而且Golang的模板工具和页面模板已经写完了。但是最近又开了个坑所以就……
无限延期吧……
写的乱糟糟的
2014-10-31 00:00
本文是研究LevelDB结构之后为了加深印象写的,然后主要是写存储过程的细节(其实本来像画个gif来实现的,但是太麻烦了……)。细节部分都是靠各种资料总结的,然后推荐先看一下文章底部的资料,因为有些重复部分没写
如有理解错误,还请指出
首先收到一个添加key的请求,先直接写入log文件(追加写入)
然后插入到内存的储存区(内存储存区内按照key的顺序排列),等到内存储存的数据达到一定大小后(1M),将内存内的数据写入level为0的sst文件内,然后删除log(这里说一下需要注意的是level0内的数据都是直接从内存写入的,所以不同sst文件的key可能会有重复,和其他level不同,其他level在合并的时候都会去掉重复key,不过level0不经过合并这个步骤(当然要是每次从内存写入的时候都更新一下也行,但是io消耗太大,不如在合并到level1的时候进行操作)。所以说level0和其他level相比,更像一个缓存数据用的)
等到level0级别的sst文件达到一定数量后,挑选其中一个sst文件合并到level1(如果没有level1那么就生成level1,其他level也是这么来的。然后因为level0会有重复key(上面也说过原因),所以合并到level1的时候会先去掉和被选中的sst文件内重复的key再合并(所以可能会涉及到level0级别的多个sst文件更新))
合并的时候会检查level0中的key是否和level1中的key有重合,如果有重合那就读取重合的文件和level0中被挑选的sst文件进行更新key,然后排序key之后再按照2M一个sst文件写入level1(这里就可以看出key按照顺序排列的好处了,因为挨着的key基本都在一个文件里,从level0里选择sst文件的key是挨着的,level1的也是,更新的话只需要更新1~2个文件,能减少需要读取的sst文件个数。比如level0抽取的sst文件key是A1~C3
的,和level1里面A1~C5
的sst刚好能重合,就只需要读取一个文件进行合并了。如果是按照插入顺序之类的乱序,可能会从N个文件里找到重复的key,合并需要读取的文件也就会更多了)
等到level1的文件数据达到10M时(每个级别最大数据量为10^level
,level1为10M,level2就是100M),就选择其中一个sst文件合并到leve2。合并方法也是找到重复的key更新,排序,然后生成sst。不过这一层的sst单个文件不再是2M,而是更大一些,每增加一层sst文件最大限制都会扩大。这样设计是为了一层满了之后不至于逐层更新。
剩下的level层也是像上面那样进行更新,所以level最大的一层,数据也是最旧的
删除操作和更新操作基本也都是直接插入数据,只不过删除操作插入的是删除标记,更新操作是直接重新插入一遍数据(在level合并的时候会进行处理更新)
在进行读取key的时候,会先从内存查找是否有这个key,然后再到level0查找,如果还是没有就会到更高层level挨个查找,因为越高层数据越旧,没有被更新到的可能也就越大(比如一个储存在level3的key被在level2标记了删除,但是还没更新到。那么当查找这个key的时候就会优先找到在level2的删除标记(当然level3的key也会在多次合并操作之后被删除掉))
本文章配合以下资料阅读更佳:
http://blog.nosqlfan.com/html/2882.html
http://www.cnblogs.com/haippy/archive/2011/12/04/2276064.html
生成器
2014-10-27 00:00
就是上一篇文章里说的那个,写完之后发现挺奇葩的
项目地址:https://github.com/Bluek404/GoHTML
介绍什么的直接扔README了:
GoHTML
██████╗ ██╗ ██╗████████╗███╗ ███╗██╗
██╔════╝ █████╗ ██║ ██║╚══██╔══╝████╗ ████║██║
██║ ███╗██╔══██╗███████║ ██║ ██╔████╔██║██║
██║ ██║██║ ██║██╔══██║ ██║ ██║╚██╔╝██║██║
╚██████╔╝╚█████╔╝██║ ██║ ██║ ██║ ╚═╝ ██║███████╗
╚═════╝ ╚════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝
Golang HTML模板,非正式项目
基本就是写着玩的
可以将Golang和HTML写在一起,然后用本工具转换成Golang文件
基本功能就是将<a>
转换成buffer.WriteString("<a>")
例子
转换前:
package tpl
import (
"fmt"
"bytes"
)
func Index() string {
_buffer := new(bytes.Buffer)
<a>Text</a>
for i:=0; i<10; i++ {
<a>{{string(i)}}</a>
}
var t string = "2"
fmt.Println(t)
print:=func() {
<a>text</a>
}
print()
test1(_buffer)
test2(_buffer, t)
return _buffer.String()
}
func test1(_buffer *bytes.Buffer) {
<a>test1</a>
}
func test2(_buffer *bytes.Buffer, t string) {
<a>test{{t}}</a>
}
转换后:
package tpl
import (
"fmt"
"bytes"
)
func Index () string {
_buffer := new ( bytes . Buffer )
_buffer . WriteString ( "<a>Text</a>" )
for i := 0 ; i < 10 ; i ++ {
_buffer . WriteString ( "<a>" )
_buffer . WriteString ( string ( i ))
_buffer . WriteString ( "</a>" )
}
var t string = "2"
fmt . Println ( t )
print := func () {
_buffer . WriteString ( "<a>text</a>" )
}
print ()
test1 ( _buffer )
test2 ( _buffer , t )
return _buffer . String ()
}
func test1 ( _buffer * bytes . Buffer ) {
_buffer . WriteString ( "<a>test1</a>" )
}
func test2 ( _buffer * bytes . Buffer , t string ) {
_buffer . WriteString ( "<a>test" )
_buffer . WriteString ( t )
_buffer . WriteString ( "</a>" )
}
然后就可以直接调用里面的函数作为http.HandleFunc
使用帮助
$ go run GoHTML.go
██████╗ ██╗ ██╗████████╗███╗ ███╗██╗
██╔════╝ █████╗ ██║ ██║╚══██╔══╝████╗ ████║██║
██║ ███╗██╔══██╗███████║ ██║ ██╔████╔██║██║
██║ ██║██║ ██║██╔══██║ ██║ ██║╚██╔╝██║██║
╚██████╔╝╚█████╔╝██║ ██║ ██║ ██║ ╚═╝ ██║███████╗
╚═════╝ ╚════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝
=====================================================
GoHTML使用帮助:
===============
命令结构:
命令 [参数] <模板文件夹路径>
参数:
-dl <字符串> | 默认:{{ | 左分隔符样式
-dr <字符串> | 默认:}} | 右分隔符样式
-suffix <字符串> | 默认:gohtml | GoHTML模板文件后缀
-buffer <字符串> | 默认:_buffer | 缓冲器变量名称
举例:
$ gohtml -dl <{ -dr }> -suffix temp -buffer buf /home/bluek404/gocode/web/view
| 则会将
| /home/bluek404/gocode/web/view
| 里面所有temp为后缀的文件转换为go文件后放到同一文件夹内
| 将缓冲器变量名称设为“buf”
| 并设置左分隔符为“<{” ,右分割符为“}>”
备注:
方括号[]为选填项目,尖括号<>为必填项目
源码规范
作为http.HandleFunc
的函数,必须返回值只有一个string
(因为多了就不符合http.HandleFunc
的要求了)
然后里面必须创建一个类型为*bytes.Buffer
的变量,变量名称需要和设置的一样(默认是_buffer
)。这个缓冲器是用于存放要输出的HTML代码的
然后作为http.HandleFunc
的函数的返回值需要是_buffer.String()
,如果你自定义了缓冲器变量名称,需要相应的改变
负责处理部分html的函数,推荐写成上面例子里的样式(接收一个缓冲器变量),就像:
func test1 ( _buffer * bytes . Buffer ) {
< a > test1 </ a >
}
因为会转换成:
func test1 ( _buffer * bytes . Buffer ) {
_buffer . WriteString ( "<a>test1</a>" )
}
这个样子
当然你要是写成函数里新建一个缓冲器变量然后再return
也是没问题的
不过那样就需要在使用函数的地方再加一个输出了(相当麻烦)
所以就乖乖按照标准写吧
然后还有一点要注意
就是分隔符输出变量那里,比如{{t}}
这里的分隔符只有在HTML中才会被转换,就像<a>{{t}}</a>
写在别的地方是不会转换的,比如:
< a >
if i == 0 {
{{ t1 }}
} else {
{{ t2 }}
}
</ a >
必须写成
if i == 0 {
< a > {{ t1 }} </ a >
} else {
< a > {{ t2 }} </ a >
}
这样才可以
自动转换
每次更新完模板后都要手动执行一次转换工具一定是超麻烦的
所以需要自动的工具
这里推荐Unknwon 的BRA (名字好像有点奇怪?),当然其他相似功能的工具也是可以的(如果有更好的还拜托推荐一下)
具体使用方法这里就不说了,自己去看吧
下载
轮子、轮子、轮
2014-10-02 00:00
目标是“完全没有可定制性”
模板已经写好了
但是后端基本没写
而且因为Golang本身的template包实在不好用
于是准备重写一个(又是大坑)
然后……
估计就没有然后了……
还是因为懒……
2014-09-03 00:00
这个高亮脚本就叫做highlightjs
因为主题比较多
所以就直接换成这个了
支持92种语言和49种高亮主题
官网:
https://highlightjs.org
主题列表&预览:
https://highlightjs.org/static/test.html
package main
import (
"fmt"
"math/rand"
"sync/atomic"
"time"
)
type readOp struct {
key int
resp chan int
}
type writeOp struct {
key int
val int
resp chan bool
}
func main () {
var ops int64
reads := make ( chan * readOp )
writes := make ( chan * writeOp )
go func () {
var state = make ( map [ int ] int )
for {
select {
case read := <- reads :
read . resp <- state [ read . key ]
case write := <- writes :
state [ write . key ] = write . val
write . resp <- true
}
}
}()
for r := 0 ; r < 100 ; r ++ {
go func () {
for {
read := & readOp {
key : rand . Intn ( 5 ),
resp : make ( chan int )}
reads <- read
<- read . resp
atomic . AddInt64 ( & ops , 1 )
}
}()
}
for w := 0 ; w < 10 ; w ++ {
go func () {
for {
write := & writeOp {
key : rand . Intn ( 5 ),
val : rand . Intn ( 100 ),
resp : make ( chan bool )}
writes <- write
<- write . resp
atomic . AddInt64 ( & ops , 1 )
}
}()
}
time . Sleep ( time . Second )
opsFinal := atomic . LoadInt64 ( & ops )
fmt . Println ( "ops:" , opsFinal )
}
Google Code Prettify
2014-09-01 00:00
使用的是Google Code Prettify
因为这个js是google code用的,所以各种语言支持比较全面(当然主要是因为Golang才用的)
直接用的默认css
所以和博客主题不是很搭
准备有时间自己修改一下(目测这几个月内是不行了)
来一段测试一下:
package main
import (
"fmt"
"math/rand"
"sync/atomic"
"time"
)
type readOp struct {
key int
resp chan int
}
type writeOp struct {
key int
val int
resp chan bool
}
func main () {
var ops int64
reads := make ( chan * readOp )
writes := make ( chan * writeOp )
go func () {
var state = make ( map [ int ] int )
for {
select {
case read := <- reads :
read . resp <- state [ read . key ]
case write := <- writes :
state [ write . key ] = write . val
write . resp <- true
}
}
}()
for r := 0 ; r < 100 ; r ++ {
go func () {
for {
read := & readOp {
key : rand . Intn ( 5 ),
resp : make ( chan int )}
reads <- read
<- read . resp
atomic . AddInt64 ( & ops , 1 )
}
}()
}
for w := 0 ; w < 10 ; w ++ {
go func () {
for {
write := & writeOp {
key : rand . Intn ( 5 ),
val : rand . Intn ( 100 ),
resp : make ( chan bool )}
writes <- write
<- write . resp
atomic . AddInt64 ( & ops , 1 )
}
}()
}
time . Sleep ( time . Second )
opsFinal := atomic . LoadInt64 ( & ops )
fmt . Println ( "ops:" , opsFinal )
}
上面这段源码来自于:
Go by Example 中文:Go 状态协程
下午茶的东西全了
2014-08-31 00:00
上面还附带一个开箱工具
外加一包铁观音
顺便在博客css里面加上了一段
.container img {
max-width: 100%;
}
这样图片就自动缩放了
FREEDOM!!
2014-08-26 00:00
在36氪看见的文章
http://www.36kr.com/p/214845.html
于是就下载使用了一下
发现Arch的aur源里已经可以安装了
yaourt -S twister-core-git twister-html-git
然后配置一下
~/.twister/twister.conf
里面填入
rpcuser=user
rpcpassword=pwd
rpcallowip=127.0.0.1
上面的用户名和密码改成你自定义的就行了
这个用户名和密码只不过是用来识别本地管理员身份的,不是twister帐号
然后移动twister-html到~/.twister/html(twister-html的位置我忘了,搜索下吧)
su切换到root运行systemctl start twister
开启服务
切换到普通用户运行twisterd
开启主程序
打开网页http://127.0.0.1:28332/index.html 输入你上面的用户名密码然后等待区块同步完成修改个人信息即可
官网:http://twister.net.co
参考信息:http://wiki.twister.net.co/w/using:howto:compiling_twister_on_ubuntu_12.04
PREV
NEXT