vim作为键盘操作为主的编辑器,有许多功能丰富的快捷键,其实不只在普通模式下有快捷键,其实在插入模式下也有一些有用的快捷键…

插入模式的快捷键

对于新手来说,vim的插入模式和记事本一样“好用”,记事本有一些快捷键,但是在vim的插入模式下,我们却经常忘记使用快捷键:

<C-h>/Ctrl+h	 删除前一个字符
<C-w> 删除前一个单词
<C-u> 删除到行首

Esc/<C-[> Esc进入普通模式,其实Ctrl+[和Esc的作用是一样的
<Ctrl-o> Ctrl+o进入插入-普通模式,此模式下可以执行一个普通模式下的命令并返回插入模式,
常用 <C-o>zz:保持插入模式并把光标行滚动到屏幕中间

可以在插入模式下使用vim的计算工具<C-r>= 插入模式下这个组合键访问表达式寄存器(=),这是会在屏幕下方提示输入运算符,输入1+2+3<CR>(回车),vim就会把运算结果插入到刚刚的光标位置,并且仍然是插入模式

对于104键的键盘可以在插入模式下使用Shift+insert组合键粘贴系统剪切板的内容,可以使用<C-r>n粘贴寄存器n中的内容

在插入模式下 <C-v>用来插入一个特殊字符,比如<C-v>u00bf可以插入一个返过来的问号~这是用来插入unicode字符的。

可视模式下的快捷键

普通模式下的快捷键

分栏

sp {filename} 水平切分上下两栏。filename可选,默认当前文件,快捷键<C-w>s
vsp {filenamem} 垂直切分,左右两栏 <C-w>v

如果安装了yadr扩展的话可以使用contrl+h,j,k,l来跳转到相应方向的分栏
没有yadr可以使用快捷键 <C-w><C-w>在分栏中循环切换,或这使用<C-w>[h,j,k,l] 跳转到分栏。

<C-w>= 所有窗口等宽等高
<C-w>_ 最大化活动窗口高度
<C-w>| 最大化活动窗口宽度
[n]<C-w>_ 活动窗口高度设为n
[n]<C-w>| 活动窗口宽度设为n

:clo 关闭活动窗口, 快捷键 <C-w>c
:on[ly] 只保留当前窗口 快捷键 <C-w>o

很有用的重新对其代码,命令模式下 gg=G
待续

前段时间去php.net上闲逛发现PHP7的beta1版本出来了,就尝试着编译安装了一下

之前在鸟哥的博客里看到了他们做的PHP的性能测试,相对于PHP5.6都是有很大的提升的,并且PHP的主版本号已经是2004年发布PHP5后,11年来首次更新,肯定PHP7是有很大的改变的,下面那就来试试PHP7的beta版吧,正式版大概在今年年底会发布。

下载源码

测试版本的PHP下载页面: https://downloads.php.net/~ab/

php7 beta1: https://downloads.php.net/~ab/php-7.0.0beta1.tar.gz

wget https://downloads.php.net/~ab/php-7.0.0beta1.tar.gz
或者
curl -O https://downloads.php.net/~ab/php-7.0.0beta1.tar.gz
阅读全文 »

effective go 中的部分笔记,这是第二部分

部分笔记摘要,参考: https://go-zh.org/doc/effective_go.html

方法/Methods

与一般的面向对象语言不同;一般的面向对象语言定义类,然后在类中定义属性和方法,通过类的继承来抽象一套机制,但是在Go中,首先是定义结构,然后为已经命名的结构(除了指针或接口)定义方法,这里有一个方法接收者的概念,为一个结构体绑定方法的常用用法如下:

type Book struct {
price float64
}

func (p Book) Disount(c float64) float64 {
// 注意int和float64类型不一样,
// 在Go中并不能直接操作,需要进行类型转换
// 但是float64 可以与字面量值直接相乘... p.price*100不会有问题
return p.price * c
}

对一些方法,传入的参数是值的拷贝而不是地址,经常需要在方法的结尾放回新的结果,可以通过把参数的指针传入,直接修改参数的地址指向的值,常见的io.Write接口就是在指针添加方法。

type byteSlice []byte
func (slice *byteSlice) Write(data []byte) (n int, err error) {

...
}

var b byteSlice
fmt.Fprintf(&b, "this is a string", 7)

以指针或值为接收者的区别在于:值方法可通过指针和值调用, 而指针方法只能通过指针来调用

接口与其他类型/interface

Go中的接口为指定对象的行为提供了一种方法:如果某样东西可以完成这个, 那么它就可以用在这里。我们已经见过许多简单的示例了;通过实现 String 方法,我们可以自定义打印函数,而通过 Write 方法,Fprintf 则能对任何对象产生输出。

Go中的的接口只是需要实现它的类接受了同名的方法即可,这是很特别的。

类型转换

下面的代码:

type squence []int
func (s squence) String stirng {
// do some thing to s
return ftm.Sprint(s)
}

如果忽略类型名,squence和[]int其实是相同的,只不过squence有一个新的类型名而已,所以在他们之间进行类型转换是可以的:

is := []int(s)

在Go语言中,为了访问不同的方法集会经常进行类型转换。甚至对int和float之间的简单运算都会用到类型转换。

接口转换与类型断言

对于混合类型,我们经常需要将一种接口转换为另一种接口,要判断一个值是否实现了某个接口,需要使用到类型断言。类型断言接受一个接口值,并从中提取指定的明确的明确类型的值。与其他语言判断类型不同,它的用法如下:

var.(typeName)
str.(string)

// 对于使用接口定义的值,可以使用下面的方式
// 其中iv是用 var iv interface{} 定义的,Milk是一中类型
switch str := iv.(type) {
case string:
fmt.Println(str)
case Milk:
fmt.Println("milk", str)
default:
fmt.Println("interface type:", str)
}

这是一个看起来很奇怪的用法,不知道Go中有没有提供想instanceof这样的关键字。

通用性/Generality

这部分还不是很了解

若某种现有的类型仅实现了一个接口,且除此之外并无可导出的方法,则该类型本身就无需导出。 仅导出该接口能让我们更专注于其行为而非实现,其它属性不同的实现则能镜像该原始类型的行为。 这也能够避免为每个通用接口的实例重复编写文档。

在这种情况下,构造函数应当返回一个接口值而非实现的类型。

接口和方法

Go中几乎任何类型(除了指针和接口)都能添加方法(添加的示例已经看过很多了,就不赘述了),因此几乎任何类型都能满足一个接口(即使是基于int的类型也能用来满足一个特别的接口),常见的用法就是任何实现了ServeHTTP方法的对象都能处理HTTP请求

甚至可以为func添加方法,当然需要先将函数定义为一种新类型

Handler接口定义如下:

type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}

下面是一个实现该接口的示例:

import "net/http"

type milkServer struct {
n int
}
// 注意参数中的http不能少,参考Go的包机制
func (m *MilkServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
m.n++
// do some thing
fmt.Fprintf(w, "request count at %d\n", m.n)
...
}

// 添加绑定
m := new(Milk)
http.Handle("/count", m)
// 也可以直接绑定一个与ServeHTTP签名相同的函数
func ArgsFunc(w http.ResponseWriter, req *http.Request) {
...
}
http.HandleFunc("args", ArgsFunc)

当然也可以绑定到一个信道上面,然后使用信道新更新一些内部状态:

type Chan chan *http.Request
func (c Chan) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c <- req
fmt.Fprint(w, "request received")
}

vim中常用的命令,日常更新

!ls  使用感叹号开头调用系统命令
~ 切换当前光标所在字符的大小写

buffer相关

:ls
:bn :bnext
:bp :bprev
:bd :bdelete
:b1 :buffer1
:bufdo cmd 在所有缓冲区执行命令

参数列表

:args 列出参数列表或者设置参数列表
:args **/*.postfix
:write :w
:edit! :e!放弃修改重新载入文件
:qall :qa
:wall :wa

多窗口

:sp [file] 水平分割
:vsp [filw] 垂直分割
:clo <C-w>c 关闭当前窗口
:no[ly] <C-v>o 关闭当前之外的所有窗口

切换窗口

<C-w><C-w> 在串口中切换,连续按两次Ctrl+w
<C-w>h|j|k|l 切换到左/下/上/右的窗口

改变窗口大小

<C-w>=
<C-w>_ 最大化当前窗口的高度
<C-w>| 最大化当前窗口的宽度
[n]<C-w>_ 设置
[n]<C-w>|

标签

:tabedit :tabe {filename} 如果filename为空则打开一个新的标签页
:tabclose :tabc
:tabonly :tabo 关闭当前标签之外的所有标签

标签切换

:tabnext  :tabn {N}  Ngt
:tabn gt
:tabp gT
:tabmove [N] 移动标签页

打开及保存文件

:edit full/path/name
:edit %:h<tab>filename 使用缓冲区文件的完整路径打开文件, :h去掉当前文件名,tab键补全
:edit path 打开文件管理窗口
:find filename 在path下查找文件
: set path+=/path/to/workspace 将工作区添加到vim的path中用于寻找
:e 是 :edit的缩写
:Explore :E 打开当前的目录管理器
:Sexplore explore的切分
:Vexplore

文件操作

:!mkdir -p %:h    前缓冲区创建目录,然后在:w,解决某些不能保存的问题
:w !sudo tee % > /dev/null 由于保存用非sudo打开的无权限文件的保存

Golang中可以使用iota方便的定义复杂的常量结构,下面是golang spec中的说明

Within a constant declaration, the predeclared identifier iota represents successive untyped integer constants. It is reset to 0 whenever the reserved word const appears in the source and increments after each ConstSpec. It can be used to construct a set of related constants:

示例1

const (  // iota is reset to 0
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
)

const (
a = 1 << iota // a == 1 (iota has been reset)
b = 1 << iota // b == 2
c = 1 << iota // c == 4
)

const (
u = iota * 42 // u == 0 (untyped integer constant)
v float64 = iota * 42 // v == 42.0 (float64 constant)
w = iota * 42 // w == 84 (untyped integer constant)
)
``
const x = iota // x == 0 (iota has been reset)
const y = iota // y == 0 (iota has been reset)

Within an ExpressionList, the value of each iota is the same because it is only incremented after each ConstSpec:

示例2

const (
bit0, mask0 = 1 << iota, 1<<iota - 1 // bit0 == 1, mask0 == 0
bit1, mask1 // bit1 == 2, mask1 == 1
_, _ // skips iota == 2
bit3, mask3 // bit3 == 8, mask3 == 7
)

This last example exploits the implicit repetition of the last non-empty expression list.

iota是一个比较有特色的东西,看完这两个例子基本就知道怎么用了,相当于它是一个从0开始自动增加的变量,可以重复使用,可以用来定义单位的大小,比如KB,MB,GB等

effective go 中的部分笔记,这是第一部分

部分笔记摘要,参考: https://go-zh.org/doc/effective_go.html

函数

Go的函数有一个很特别的性质那就是多值返回,这样做有一个很方便的地方是可以把错误值返回,这样做和后面会讲到的取消异常也是有关的。

一个Go函数的签名可能是:

func (file *File) Write(b []byte) (n int, err error)

这是一个典型的Go函数签名,初看起来比较复杂,一点点分析:

  1. func关键字,类似php中的function
  2. (file File) 表示这是一个添加到File接口上的方法。这也是Go比较有意思的地方,通过附着接口方法的方式实现接口
  3. Write 很简单就是方法名了,大写开头的方法表示共有的导出方法,如果是小写的方法名是不能导出的
  4. (b []byte)方法的参数,形参名为b,类型为[]byte
  5. (n int, err error) 返回类型,如果是多指返回则使用小括号括起来,如果是一个返回值就不需要了。比较有意思的是返回值也可以作为有命名返回值,比如这里的n和err,这样表示把函数作用域内的n和err变量返回,这样返回语句只需要写return,而不需要显式说明具体变量

Defer

Defer 是Go的关键字,用于预设一个函数调用,一个使用Defer调用的函数会在执行defer的函数返回之前立即执行,常用来释放资源,比如解锁互斥和关闭文件
使用defer推迟的函数会按照后进先出的顺序执行。

阅读全文 »

这部分包含的内容:

  1. 什么是ambari
  2. 如何安装Ambari
  3. 安装hadoop集群的准备工作
  4. 如何使用Ambari搭建一个集群
  5. 其他

什么是Ambari

Ambari是的apache基金会下的一个开源项目。其目标是简化Hadoop集群的管理。通过Ambari提供工具可以方便的配置、管理、监控Hadoop集群。Ambari提供了一个直观的,易用的Hadoop管理web界面。Ambari现在最新的版本为2.0.0,但是网上比较多的资料都是1.2-1.7的。

作为一个开源项目,Hadoop在的配置与管理一直非常的不友好,要配置一个Hadoop集群经常会出现各种问题,并且对于集群的监控也比较麻烦,这也是像cloudera、hortonworks这类的提供Hadoop服务的公司可以存在的理由。

Ambari架构采用的是Server/Client的模式,主要组件:ambari-agent、ambari-server和ambari-web。ambari-agent是一个无状态的, 采集所在节点的信息并且汇总发心跳汇报给ambari-server, 处理ambari-server的执行请求。

阅读全文 »