mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-08-11 23:08:34 +08:00
精校:9.2-9.4
This commit is contained in:
@@ -19,4 +19,4 @@ Golang 编程:245386165
|
||||
|
||||
|更新日期 |更新内容
|
||||
|----------|------------------
|
||||
|2015-08-04|8.6 将 map 的键值对调
|
||||
|2015-08-06|9.4 精密计算和 big 包
|
5
TOC.md
5
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)
|
||||
- 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)
|
@@ -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 节)。
|
||||
|
||||
## 链接
|
||||
|
||||
|
@@ -8,22 +8,41 @@
|
||||
|
||||
在 Go 语言中这种锁的机制是通过 sync 包中 Mutex 来实现的。sync 来源于 "synchronized" 一词,这意味着线程将有序的对同一变量进行访问。
|
||||
|
||||
sync.Mutex 是一个互斥锁,它的作用是守护在临界区入口来确保同一时间只能有一个线程进入临界区。
|
||||
`sync.Mutex` 是一个互斥锁,它的作用是守护在临界区入口来确保同一时间只能有一个线程进入临界区。
|
||||
|
||||
假设 info 是一个需要上锁的放在共享内存中的变量。通过包含 Mutex 来实现的一个典型例子如下:
|
||||
假设 info 是一个需要上锁的放在共享内存中的变量。通过包含 `Mutex` 来实现的一个典型例子如下:
|
||||
|
||||
```go
|
||||
import “sync”
|
||||
import “sync”
|
||||
|
||||
type Info struct {
|
||||
mu sync.Mutex
|
||||
// ... other fields, e.g.: Str string
|
||||
}
|
||||
```
|
||||
|
||||
如果一个函数想要改变这个变量可以这样写:
|
||||
|
||||
```go
|
||||
func Update(info *Info) {
|
||||
mu sync.Mutex
|
||||
// ... other fields, e.g.: Str string
|
||||
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 包可以解决同一时间只能一个线程访问变量或 map 类型数据的问题。如果这种方式导致程序明显变慢或者引起其他问题,我们要重新思考来通过 goroutines 和 channels 来解决问题,这是在 Go 语言中所提倡用来实现并发的技术。我们将在第 14 章对其深入了解,并在第 14.7 节中对这两种方式进行比较。
|
||||
|
||||
|
@@ -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)
|
||||
# 精密计算和 big 包
|
Reference in New Issue
Block a user