Git 常用命令详解(二)

Git Community Book 中文版

Git 是一个很强大的分布式版本管理工具,它不但适用于管理大型开源软件的源代码(如:linux kernel),管理私人的文档和源代码也有很多优势(如:wsi-lgame-pro

Git 的更多介绍,请参考我的上一篇博客:Git 版本管理工具

一、 Git 命令初识

在正式介绍Git命令之前,先介绍一下Git 的基本命令和操作,对Git命令有一个总体的认识

示例:从Git 版本库的初始化,通常有两种方式:

1)git clone:这是一种较为简单的初始化方式,当你已经有一个远程的Git版本库,只需要在本地克隆一份

例如:git  clone  git://github.com/someone/some_project.git   some_project

上面的命令就是将’git://github.com/someone/some_project.git’这个URL地址的远程版本库,完全克隆到本地some_project目录下 Continue reading

使用php中的反射,定位函数所在位置

用反射,比如想知道函数hello是哪个文件里的哪行定义的:

$obj = new ReflectionFunction("hello");
$file = $obj->getFileName();
$line = $obj->getStartLine();

关于php中的反射请参考官方手册:http://www.php.net/manual/zh/book.reflection.php

mysql中的表锁的优化

一、获取锁等待情况

可以通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺:
mysql> show status like ‘Table%’;
+—————————-+———-+
| Variable_name       | Value |
+—————————-+———-+
| Table_locks_immediate   | 105       |
| Table_locks_waited  | 3     |
+—————————-+———-+
2 rows in set (0.00 sec)

Table_locks_immediate 表示立即释放MySQL表锁数,
Table_locks_waited 表示需要等待的MySQL表锁数
如果Table_locks_waited的值比较高,则说明存在着较严重的表级锁争用情况。这时,需要我们对应用做进一步的检查,来确定问题所在。

可以通过检查Innodb_row_lock状态变量来分析系统上的行锁的争夺情况:
mysql> show status like ‘innodb_row_lock%’;
+—————————————-+———-+
| Variable_name               | Value |
+—————————————-+———-+
| Innodb_row_lock_current_waits   | 0     |
| Innodb_row_lock_time            | 2001  |
| Innodb_row_lock_time_avg        | 667       |
| Innodb_row_lock_time_max    | 845       |
| Innodb_row_lock_waits       | 3     |
+—————————————-+———-+
5 rows in set (0.00 sec)
Continue reading

动态执行ajax请求里的js代码

index.html

<script src=”/js/jquery.js”></script>
<script>
function evalScript(html) {
// var html = response.responseText;
var hd = document.getElementsByTagName(“head”)[0];
var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
var srcRe = /\ssrc=([\’\”])(.*?)\1/i;
var typeRe = /\stype=([\’\”])(.*?)\1/i;
var match;
while(match = re.exec(html)){
var attrs = match[1];
var srcMatch = attrs ? attrs.match(srcRe) : false;
if(srcMatch && srcMatch[2]){
var s = document.createElement(“script”);
s.src = srcMatch[2];
var typeMatch = attrs.match(typeRe);
if(typeMatch && typeMatch[2]){
s.type = typeMatch[2];
}
hd.appendChild(s);
}else if(match[2] && match[2].length > 0){
if(window.execScript) {
window.execScript(match[2]);
} else {
window.eval(match[2]);
}
}
}
}

$(function(){
$.get(‘b.html’,{},function(html){
evalScript(html);
alert(sysmsg);
})
})
</script>

ajax.html

<script type="text/javascript" src="test.js"></script><script type="text/javascript" src="ts.js"></script>
<script type="text/javascript">// <![CDATA[
alert('aaaa');
// ]]></script>
<script type="text/javascript">// <![CDATA[
var sysmsg = '1';
// ]]></script>

golang中结构体的初始化方法的不同用法(new方法)

自定义一个结构体

type Rect struct {
    x, y float64
    width, height float64
}

初始化方法:

rect1 := new(Rect)
rect2 := &Rect{}
rect3 := &Rect{0, 0, 100, 200}
rect4 := &Rect{width:100, height:200}

注意这几个变量全部为指向Rect结构的指针(指针变量),因为使用了new()函数和&操作符。

而如果使用方法 Continue reading

golang中的文档管理

foo.go

// CopyRight  2013 The Go Author. All Right reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE fifle.

/*
Package foo implements a set of simple mathematical functions. These comments are for
demonstration purpose only. Nothing more.

If you have any questions,please don't hesitate to add yourself to
golang-uns@googlegroups.com.

you can alse visit golang.org for full Go documentation.
*/

package foo

import (
	"fmt"
)

// Foo compares the two input values and retrens the larger
// Value, If the two values are equal, return 0.
func Foo(a, b int) (ret int, err error) {
	if a > b {
		return a, nil
	} else {
		return b, nil
	}

	return 0, nil
}

// BUG(jack): #1: i'm sorry but this code has an issue to be solved.

// BUG(tom): #2: An issue assigned to anothoer person.

生成文档摘要

go doc foo.go
PACKAGE DOCUMENTATION
	
	package foo
	    import "D:\gotest\src"
	
	
	
	FUNCTIONS
	
	func Foo(a, b int) (ret int, err error)
	    Foo compares the two input values and retrens the larger Value, If the
	    two values are equal, return 0.
	
	
	
	BUGS
	
	   #1: i'm sorry but this code has an issue to be solved.
	
	   #2: An issue assigned to anothoer person.

为了方便查看,也可以通过浏览器查看

godoc -http=:9090

然后输入 http://localhost:9090/pkg/foo 即可

golang中的map数据类型操作实例


package main

import (
 "fmt"
)

type stu struct {
 Name string
 Age int
}

func main() {

//声明一个map变量student,键名为string,值为stu
 var student map[string]stu

//给map变量创建值,同时指定最多可以存储5个stu值
 student = make(map[string]stu, 5)

//map元素赋值
 student["stu1"] = stu{"zhao", 25}
 student["stu2"] = stu{"zhang", 28}
 student["stu3"] = stu{"sun", 32}
 student["stu4"] = stu{"li", 40}
 student["stu5"] = stu{}

//上面方式的简写方法
 /* 
student := map[string]stu{
 "stu1": stu{"zhao", 25},
 "stu2": stu{"zhang", 28},
 "stu3": stu{"sun", 32},
 "stu4": stu{"li", 40},
 "stu5": stu{},
 }
*/

//打印map信息
 fmt.Printf("%v\n", student)

//查询一个map值
 s1, ok := student["stu2"]
 if ok {
 fmt.Println("Found stu2, Name:", s1.Name)
 } else {
 fmt.Println("Not Found stu2")
 }

//删除一个map值,如果stu2不存在,则什么也不会发生,但如果传入的map变量的值为nil的话,则会抛出一个 panic 异常
 delete(student, "stu2")

fmt.Printf("%v\n", student)

}

执行结果如下:

go run map.go
[ `go run map.go` | done: 2.3907474s ]
	map[stu1:{zhao 25} stu2:{zhang 28} stu3:{sun 32} stu4:{li 40} stu5:{ 0}]
	Found stu2, Name: zhang
	map[stu1:{zhao 25} stu3:{sun 32} stu4:{li 40} stu5:{ 0}]

go语言单元测试

Go本身提供了一套轻量级的测试框架.符合规则的测试代码会在运行测试时被自动识别并执行.单元测试源文件的命名规则如平衡点:在需要测试的包下面创建以”_test”结尾的go文件,开如[^.]*_test.go

Go单元测试函数分为两在类.功能测试函数性能测试函数,分别以TestBenchmark为函数名前缀并以*testing.T 和 *testing.B 为单一参数的函数。

func TestAdd1(t *testing.T)
func BenchmarkAdd1(t *testing.T)

测试工具会根据函数中的实际执行动作得到不同的测试结果。

功能测试函数会根据测试代码执行过程中是否发生错误来反馈结果;
性能测试函数仅仅打印出来测试所花费时间,用来判断程序性能;

准备

新建一个文件,命名为 go_test.go

package go_test

import "testing"

func Add(a, b int) int {
return a + b
}

功能测试

在go_test.go文件里添加以下代码

func TestAdd1(t *testing.T) {
r := Add(1, 2)
if r != 2 { //这里为了测试,写成2
t.Errorf("Add(1,2) failed. Got %d, expected 3.", r)
}
}

执行功能单元测试非常的简单,直接执行

go test

输出以下内容

--- FAIL: TestAdd1 (0.00s)
go_test.go:12: Add(1,2) failed. Got 3, expected 3.
FAIL
exit status 1
FAIL gotest 0.130s

可以看到输出具体出错的位置为第12行,控制台并打印出了用户定义的错误信息。最后的FAIL表示测试未通过,如果为 ok 的话,则为通过。我们修正问题后再次执行结果为

PASS
ok gotest 0.146s

如果你在同一个文件里添加了多个测试函数的话,直接执行 go test,发现只要有一个函数未通过,则打印结果只有一个FAIL,对用户不太友好,这时可以使用 -v 参数 go test -v,表示输出每个功能函数的详情的信息。

=== RUN TestAdd1
--- FAIL: TestAdd1 (0.00s)
go_test.go:12: Add(1,2) failed. Got 3, expected 3.
FAIL
exit status 1
FAIL gotest 0.208s

=== RUN 行表示执行的函数
— FAIL 行表示上行执行的函数结果,如果测试通过则为 PASS
第三行 表示FAIL后的打印错误信息,如果函数测试通过是没有这一行的
第四行 表示本次测试的结果,只要有一个函数未通过,就为FAIL
如果有多个函数的话,则重复打印前两行。

*testing.T 中有一个 t.Errorf() 函数打印一些错误信息后中止测试。

说明:

对于 go test 命令如果一个文件中有一个方法未通过,则直接输出 FAIL,如果想知道具体哪个方法未通过,需要使用 -v 参数来定位。

性能测试

上面我们介绍了功能测试,再来看下性能测试。可以与功能测试在同一个文件中,默认情况下go test 并不会执行Benchmark测试,必须使用参数 ” -bench <pattern>” 指定性能测试函数。在go_test.go文件中添加以下函数。(记得先修正功能测试未通过的问题)

func BenchmarkAdd1(b *testing.B) {
for i := 0; i < b.N; i++ {
    Add(1, 2)
}
}

我们可以看出,性能测试与功能测试代码相比,最大的区别在于代码里的这个for循环,循环b.N次.写这个for循环的原因是为了能够让测试运行足够长的时间便于进行平均运行时间的计算.如果测试代码中一些准备工作的时间太长,我们也可以这样处理以明确排除这些准备工作所花费时间对于性能测试的时间影响:

func BenchmarkAdd1(b *testing.B) {
    b.Stoptimer()
    DoPreparation()
    b.StartTimer()

    for i := 0; i < b.N; i++ { //b.N,测试循环次数 
Add(1, 2)
}
}

性能单元的执行与功能测试一样简单,只不过调用时需要-test.bench参数而已,具体代码如下所示:

$go test -bench=".*"
goos: darwin
goarch: amd64
pkg: gotest
BenchmarkAdd1-4 1000000000 0.367 ns/op
PASS
ok gotest 0.698s

结果解释

goos: 表示平台系统,这里是mac
goarch: amd64 表示64位系统
pkg: 表示包名
BenchmarkAdd1-4: 表示测试的函数名称,-后面的数字表示cpu个数
1000000000: 表示共执行了 1000000000 次
0.367 ns/op: 表示每次执行耗时0.267纳秒,这里肯定是越小越好

另外对性能测试还支持一些其它的参数

  • benchmem:输出内存分配统计
  • benchtime:指定测试时间
  • cpu:指定GOMAXPROCS
  • timeout:超时限制
$ go test -v -bench=. -cpu=2 -benchtime="3s" -timeout="5s" -benchmem
=== RUN TestAdd1
--- PASS: TestAdd1 (0.00s)
goos: darwin
goarch: amd64
pkg: gotest
BenchmarkAdd1-2 1000000000 0.325 ns/op 0 B/op 0 allocs/op
PASS
ok gotest 0.460s

结果解释

BenchmarkAdd1-2: 测试函数名称,后面的2表示2个cpu线程
0 B/op:表示每次执行分配的内存(字节)
0 allocs/op:表示每次执行分配了多少次对象

从上面可以看出对于功能测试的命令为 go test,而对于性能测试则是 go test-test.bench add.go (在调用的时候添加 -test.bench参数而已)

 go test 的两种运行模式:

目录模式:当没有指定包参数时,如go test 或者 go test -v, 则在用户当前所在目录查找单元测试文件并执行,最后打印结果。这种模式下缓存功能是禁用的。

包列表板式:显示指定了包名,如(‘go test math’, ‘go test ./…’, and even ‘go test .’)

go test 的用法很灵活,如 -run 参数
 
-run regex:指定要执行的测试函数
 
// go test -run ” # Run all tests.
// go test -run Foo # Run top-level tests matching “Foo”, such as “TestFooBar”.
// go test -run Foo/A= # For top-level tests matching “Foo”, run subtests matching “A=”.
// go test -run /A=1 # For all top-level tests, run subtests matching “A=1”.

除了对项目中的所有文件进行单元测试外,还可以对指定的包进行单元测试,如对于整个 simplemath 包进行单元测试:

$go test simplemath
PASS
ok simplemath 0.013s
对于更详情的用法可以使用 go help test 了解。
 
对于 testing 包中的一些常用函数可以在文件中/src/testing/testing.go 找到。
 

性能分析工具pprof 

对于性能测试结果只是程序的最终性能报告,但对于系统中性能瓶颈在哪个地方却无法给出,所以就引出另一个问题,如何对性能进行精确定位。这就需要用到go tool了

这里可以使用 go test -v -bench=”.*” -cpuprofile=cpu.prof -c` (参考:http://www.cnblogs.com/yjf512/archive/2013/01/18/2865915.html)

cpuprofile是表示生成的cpu profile文件

-c是生成可执行的二进制文件,这个是生成状态图必须的,它会在本目录下生成可执行文件mymysql.test

然后使用go tool pprof工具

go tool pprof mymysql.test cpu.prof

==========================

文件mymath.go

package mymath

func Add(a, b int) int {
	return a + b
}
func Max(a, b int) (ret int) {
	ret = a
	if b < a {
		ret = b
	}
	return
}

测试文件 mymath_test.go(所有测试文件都必须以*_test.go结尾) Continue reading

Redis配置文件参数说明

配置文件参数说明:

1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程

daemonize no

2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定

pidfile /var/run/redis.pid

3. 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字

port 6379

4. 绑定的主机地址 Continue reading