diff --git a/README_gc.md b/README_gc.md index 3bd0c9d..1545e12 100644 --- a/README_gc.md +++ b/README_gc.md @@ -19,4 +19,4 @@ Golang 编程:245386165 |更新日期 |更新内容 |----------|------------------ -|2015-08-04|8.6 将 map 的键值对调 \ No newline at end of file +|2015-08-06|9.4 精密计算和 big 包 \ No newline at end of file diff --git a/TOC.md b/TOC.md index 934669d..58ee7d8 100644 --- a/TOC.md +++ b/TOC.md @@ -68,4 +68,7 @@ - 8.5 [map 的排序](eBook/08.5.md) - 8.6 [将 map 的键值对调](eBook/08.6.md) - 第9章:[包(package)](eBook/09.0.md) - - 9.1 [标准库概述](eBook/09.1.md) \ No newline at end of file + - 9.1 [标准库概述](eBook/09.1.md) + - 9.2 [regexp 包](eBook/09.2.md) + - 9.3 [锁和 sync 包](eBook/09.3.md) + - 9.4 [精密计算和 big 包](eBook/09.4.md) \ No newline at end of file diff --git a/eBook/09.2.md b/eBook/09.2.md index 8e52f38..88d4c7f 100644 --- a/eBook/09.2.md +++ b/eBook/09.2.md @@ -1,14 +1,22 @@ # 9.2 regexp 包 -正则表达式语法和使用的详细信息请参考 http://en.wikipedia.org/wiki/Regular_expression +正则表达式语法和使用的详细信息请参考 [维基百科](http://en.wikipedia.org/wiki/Regular_expression)。 在下面的程序里,我们将在字符串中对正则表达式进行匹配。 -如果是简单模式,使用 Match 方法便可:`ok, _ := regexp.Match(pat, []byte(searchIn))` +如果是简单模式,使用 `Match` 方法便可: -变量 ok 将返回 true 或者 false,我们也可以使用 MatchString:`ok, _ := regexp.MathString(pat, searchIn)` +```go +ok, _ := regexp.Match(pat, []byte(searchIn)) +``` -更多方法中,必须先将正则通过 Compile 方法返回一个 Regexp 对象。然后我们将掌握一些匹配,查找,替换相关的功能。 +变量 ok 将返回 true 或者 false,我们也可以使用 `MatchString`: + +```go +ok, _ := regexp.MathString(pat, searchIn) +``` + +更多方法中,必须先将正则通过 `Compile` 方法返回一个 Regexp 对象。然后我们将掌握一些匹配,查找,替换相关的功能。 示例 9.2 [pattern.go](examples/chapter_9/pattern.go): @@ -49,7 +57,7 @@ func main() { John: ##.# William: ##.# Steve: ##.# John: 5156.68 William: 9134.46 Steve: 11264.36 -Compile 函数也可能返回一个错误,我们在使用时忽略对错误的判断是因为我们确信自己正则表达式是有效的。当用户输入或从数据中获取正则表达式的时候,我们有必要去检验它的正确性。另外我们也可以使用 MustCompile 方法,它可以像 Compile 方法一样检验正则的有效性,但是当正则不合法时程序将 panic(详情查看第 13.2 节)。 +`Compile` 函数也可能返回一个错误,我们在使用时忽略对错误的判断是因为我们确信自己正则表达式是有效的。当用户输入或从数据中获取正则表达式的时候,我们有必要去检验它的正确性。另外我们也可以使用 `MustCompile` 方法,它可以像 `Compile` 方法一样检验正则的有效性,但是当正则不合法时程序将 panic(详情查看第 13.2 节)。 ## 链接 diff --git a/eBook/09.3.md b/eBook/09.3.md index 66ccff5..a01dd78 100644 --- a/eBook/09.3.md +++ b/eBook/09.3.md @@ -8,22 +8,41 @@ 在 Go 语言中这种锁的机制是通过 sync 包中 Mutex 来实现的。sync 来源于 "synchronized" 一词,这意味着线程将有序的对同一变量进行访问。 -sync.Mutex 是一个互斥锁,它的作用是守护在临界区入口来确保同一时间只能有一个线程进入临界区。 +`sync.Mutex` 是一个互斥锁,它的作用是守护在临界区入口来确保同一时间只能有一个线程进入临界区。 -假设 info 是一个需要上锁的放在共享内存中的变量。通过包含 Mutex 来实现的一个典型例子如下: +假设 info 是一个需要上锁的放在共享内存中的变量。通过包含 `Mutex` 来实现的一个典型例子如下: ```go -import “sync” type Info struct { mu sync.Mutex // ... other fields, e.g.: Str string } ``` ```go 如果一个函数想要改变这个变量可以这样写: +import “sync” +type Info struct { + mu sync.Mutex + // ... other fields, e.g.: Str string +} +``` + +如果一个函数想要改变这个变量可以这样写: + +```go func Update(info *Info) { - info.mu.Lock() // critical section: info.Str = // new value // end critical section info.mu.Unlock() } ``` 还有一个很有用的例子是通过 Mutex 来实现一个可以上锁的共享缓冲器: - ```go type SyncedBuffer struct { + info.mu.Lock() + // critical section: + info.Str = // new value + // end critical section + info.mu.Unlock() +} +``` + +还有一个很有用的例子是通过 Mutex 来实现一个可以上锁的共享缓冲器: + +```go +type SyncedBuffer struct { lock sync.Mutex buffer bytes.Buffer } ``` -在 sync 包中还有一个 RWMutex 锁:他能通过 RLock() 来允许同一时间多个线程对变量进行读操作,但是只能一个线程进行写操作。如果使用 Lock() 将和普通的 Mutex 作用相同。包中还有一个方便的 Once 类型变量的方法 once.Do(call),这个方法确保被调用函数只能被调用一次。 +在 sync 包中还有一个 `RWMutex` 锁:他能通过 `RLock()` 来允许同一时间多个线程对变量进行读操作,但是只能一个线程进行写操作。如果使用 `Lock()` 将和普通的 `Mutex` 作用相同。包中还有一个方便的 `Once` 类型变量的方法 `once.Do(call)`,这个方法确保被调用函数只能被调用一次。 相对简单的情况下,通过使用 sync 包可以解决同一时间只能一个线程访问变量或 map 类型数据的问题。如果这种方式导致程序明显变慢或者引起其他问题,我们要重新思考来通过 goroutines 和 channels 来解决问题,这是在 Go 语言中所提倡用来实现并发的技术。我们将在第 14 章对其深入了解,并在第 14.7 节中对这两种方式进行比较。 diff --git a/eBook/09.4.md b/eBook/09.4.md index 1905c00..f4a5268 100644 --- a/eBook/09.4.md +++ b/eBook/09.4.md @@ -1,22 +1 @@ -# 精密计算和 big 包 - -我们知道有些时候通过编程的方式去进行计算是不精确的。如果你使用 Go 语言中的 float64 类型进行浮点运算,返回结果将精确到 15 位,足以满足大多数的任务。当对超出 int64 或者 uint64 类型这样的大数进行计算时,如果对精度没有要求,float32 或者 float64 可以胜任,但如果对精度有严格要求的时候,我们不能使用浮点数,在内存中它们只能被近似的表示。 - -对于整数的高精度计算 Go 语言中提供了 big 包。其中包含了 math 包:有用来表示大整数的 `big.Int` 和表示大有理数的 `big.Rat` 类型(可以表示为 2/5 或 3.1416 这样的分数,而不是无理数或 π)。这些类型可以实现任意位类型的数字,只要内存足够大。缺点是更大的内存和处理开销使它们使用起来要比内置的数字类型慢很多。 - -大的整型数字是通过 `big.NewInt(n)` 来构造的,其中 n 位 int64 类型整数。而大有理数是用过 `big.NewRat(N,D)` 方法构造。N(分子)和 D(分母)都是 int64 型整数。因为 Go 语言不支持运算符重载,所以所有大数字类型都有像是 Add() 和 Mul() 这样的方法。它们作用于作为 receiver 的整数和有理数,大多数情况下它们修改 receiver 并以 receiver 作为返回结果。因为没有必要创建 big.Int 类型的临时变量来存放中间结果,所以这样的运算可通过内存链式存储。 - -示例 9.2 [big.go](examples/chapter_9/big.go): - -```go -package main import ( "fmt" "math" "math/big" ) func main() { // Here are some calculations with bigInts: im := big.NewInt(math.MaxInt64) in := im io := big.NewInt(1956) ip := big.NewInt(1) ip.Mul(im, in).Add(ip, im).Div(ip, io) fmt.Printf("Big Int: %v\n", ip) // Here are some calculations with bigInts: rm := big.NewRat(math.MaxInt64, 1956) rn := big.NewRat(-1956, math.MaxInt64) ro := big.NewRat(19, 56) rp := big.NewRat(1111, 2222) rq := big.NewRat(1, 1) rq.Mul(rm, rn).Add(rq, ro).Mul(rq, rp) fmt.Printf("Big Rat: %v\n", rq) } -``` - 输出结果: - - Big Int: 43492122561469640008497075573153004 Big Rat: -37/112 - -## 链接 - -- [目录](directory.md) -- 上一节:[锁和 sync 包](09.3.md) -- 下一节:[自定义包和可见性](09.5.md) +# 精密计算和 big 包 我们知道有些时候通过编程的方式去进行计算是不精确的。如果你使用 Go 语言中的 float64 类型进行浮点运算,返回结果将精确到 15 位,足以满足大多数的任务。当对超出 int64 或者 uint64 类型这样的大数进行计算时,如果对精度没有要求,float32 或者 float64 可以胜任,但如果对精度有严格要求的时候,我们不能使用浮点数,在内存中它们只能被近似的表示。 对于整数的高精度计算 Go 语言中提供了 big 包。其中包含了 math 包:有用来表示大整数的 `big.Int` 和表示大有理数的 `big.Rat` 类型(可以表示为 2/5 或 3.1416 这样的分数,而不是无理数或 π)。这些类型可以实现任意位类型的数字,只要内存足够大。缺点是更大的内存和处理开销使它们使用起来要比内置的数字类型慢很多。 大的整型数字是通过 `big.NewInt(n)` 来构造的,其中 n 位 int64 类型整数。而大有理数是用过 `big.NewRat(N,D)` 方法构造。N(分子)和 D(分母)都是 int64 型整数。因为 Go 语言不支持运算符重载,所以所有大数字类型都有像是 `Add()` 和 `Mul()` 这样的方法。它们作用于作为 receiver 的整数和有理数,大多数情况下它们修改 receiver 并以 receiver 作为返回结果。因为没有必要创建 `big.Int` 类型的临时变量来存放中间结果,所以这样的运算可通过内存链式存储。 示例 9.2 [big.go](examples/chapter_9/big.go): ```go package main import ( "fmt" "math" "math/big" ) func main() { // Here are some calculations with bigInts: im := big.NewInt(math.MaxInt64) in := im io := big.NewInt(1956) ip := big.NewInt(1) ip.Mul(im, in).Add(ip, im).Div(ip, io) fmt.Printf("Big Int: %v\n", ip) // Here are some calculations with bigInts: rm := big.NewRat(math.MaxInt64, 1956) rn := big.NewRat(-1956, math.MaxInt64) ro := big.NewRat(19, 56) rp := big.NewRat(1111, 2222) rq := big.NewRat(1, 1) rq.Mul(rm, rn).Add(rq, ro).Mul(rq, rp) fmt.Printf("Big Rat: %v\n", rq) } ``` 输出结果: Big Int: 43492122561469640008497075573153004 Big Rat: -37/112 ## 链接 - [目录](directory.md) - 上一节:[锁和 sync 包](09.3.md) - 下一节:[自定义包和可见性](09.5.md) \ No newline at end of file