9.2.4 包log
log是 Go 语言标准库中的一个包,用于输出日志信息。包log提供了多种级别的日志记录和灵活的配置选项,使得开发者可以在应用程序中轻松地添加日志功能。log是Go 语言中一个非常实用的包,提供了灵活的选项来记录应用程序的行为和状态。在开发过程中,它通常被用来调试代码和捕获错误。
在包log中主要提供了如下所示的内置函数:
- Print():打印普通日志信息。
- Printf():按格式打印日志信息。
- Println():打印带换行符的日志信息。
- Fatal():打印日志信息并退出程序。
- Fatalf():按格式打印日志信息并退出程序。
- Fatalln():打印带换行符的日志信息并退出程序。
- Panic():打印日志信息并引发 panic。
- Panicf():按格式打印日志信息并引发 panic。
- Panicln():打印带换行符的日志信息并引发 panic。
实例9-3:打印输出日志信息(源码路径:Go-codes\9\rizhi.go)
实例文件rizhi.go的具体实现代码如下所示。
import (
"log"
)
func main() {
// 打印普通日志信息
log.Print("This is a normal log message\n")
// 按格式打印日志信息
name := "Alice"
age := 25
log.Printf("%s is %d years old\n", name, age)
// 打印带换行符的日志信息
log.Println("Error: could not open file")
// 打印日志信息并退出
log.Fatal("An error occurred and the program is exiting\n")
// 引发 panic 并打印日志信息
log.Panic("A panic has occurred\n")
}
在上述代码中,使用 log 包输出了不同级别的日志信息。注意,在默认情况下,这些日志消息会输出到标准错误流中,所以在开发工具的调试面板中显示为错误信息颜色:红色。执行后会输出:
2023/08/27 23:18:52 This is a normal log message
2023/08/27 23:18:52 Alice is 25 years old
2023/08/27 23:18:52 Error: could not open file
2023/08/27 23:18:52 An error occurred and the program is exiting
9.2.5 包bytes
bytes是 Go 语言标准库中的一个十分重要的包,用于操作字节切片。bytes提供了许多函数来处理字节切片,例如连接、比较、搜索和替换等操作。在包bytes中主要包含如下所示的内置成员:
- 方法Compare():比较两个字节切片的大小。
- 方法Contains():判断一个字节切片是否包含另一个字节切片。
- 方法Count():计算一个字节切片中另一个字节切片出现的次数。
- 方法Join():将多个字节切片连接成一个字节切片。
- 方法Split():根据指定的分隔符将一个字节切片分割成多个子切片。
- 方法Trim():去掉一个字节切片开头和结尾的指定字符。
- 方法Replace():将一个字节切片中的指定字符替换为另一个字符。
- Buffer类型:表示一个缓存的字节数组,提供了对它的读、写、操作等功能。
- 方法Copy():用于从源切片向目标切片复制内容。
- 方法Buffer.Write():用于将字节切片写入缓存中。
- 方法Buffer.Bytes():返回缓存的内容作为一个字节切片。
- 方法Slice():对指定的切片进行排序。
实例9-4:拆分一组数字并排序(源码路径:Go-codes\9\chai.go)
实例文件chai.go的具体实现代码如下所示。
import (
"bytes"
"fmt"
"sort"
)
func main() {
// 定义一个字节数组
b := []byte{1, 4, 2, 8, 5, 7, 3, 9, 6, 0, 11, 15, 13, 10, 12, 14}
// 将字节数组分成 4 个数字一块的小块
blockSize := 4
blocks := make([][]byte, 0)
for i := 0; i < len(b); i += blockSize {
end := i + blockSize
if end > len(b) {
end = len(b)
}
block := make([]byte, end-i)
copy(block, b[i:end])
blocks = append(blocks, block)
}
// 对每个小块进行排序
for _, block := range blocks {
sort.Slice(block, func(i, j int) bool {
return block[i] < block[j]
})
}
// 将所有小块连接起来
var buffer bytes.Buffer
for _, block := range blocks {
buffer.Write(block)
}
sortedBytes := buffer.Bytes()
// 输出排序后的字节数组
fmt.Println(sortedBytes)
}
在上述代码中,首先将原始字节数组分成了若干个固定大小的小块,并对每个小块进行排序。然后,我们使用bytes.Buffer类型来连接所有小块,最终得到一个完整的排序后的字节数组。执行后会输出:
[1 2 4 8 3 5 7 9 0 6 11 15 10 12 13 14]
上述执行结果是将原始字节数组按升序排序后得到的新字节数组。首先将原始字节数组 {1, 4, 2, 8, 5, 7, 3, 9, 6, 0, 11, 15, 13, 10, 12, 14} 分成了四个数字一块的小块,即 [[1 4 2 8] [5 7 3 9] [6 0 11 15] [13 10 12 14]]。然后,对每个小块进行排序,得到 [[1 2 4 8] [3 5 7 9] [0 6 11 15] [10 12 13 14]]。最后,我们使用bytes.Buffer类型来连接所有小块,得到一个完整的排序后的字节数组 [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]。
9.2.6 包big
在 Go 语言中,包big提供了高精度数学计算的函数和类型,可以用于进行任意长度的整数计算、有理数计算和浮点数计算。在包big中包含如下所示的的整数类型。
- Int 类型:用于表示任意精度整数。
- Rat 类型:用于表示任意精度分数,即有理数。
- Float 类型:用于表示任意精度浮点数。
其中,Int 类型和 Rat 类型都支持基本的数学运算,例如加减乘除、取模、幂等操作。这些操作的函数名称和普通整数的函数名称相同,只是前面多了一个 big 前缀,例如如下所示的内置函数:
- big.NewInt(n):创建一个值为 n 的新的 Int 对象。
- x.Add(y, z):将 y 和 z 相加,并将结果存储到 x 中。
- x.Sub(y, z):将 y 减去 z,并将结果存储到 x 中。
- x.Mul(y, z):将 y 乘以 z,并将结果存储到 x 中。
- x.Quo(y, z):将 y 除以 z,并将结果存储到 x 中。
- x.Mod(y, z):计算 y 对 z 取模的结果,并将结果存储到 x 中。
- x.Exp(y, z, m):计算 y 的 z 次方,对 m 取模后的结果,并将结果存储到 x 中。
在数学应用中,阶乘是一个自然数的连乘积,例如 5! = 5 * 4 * 3 * 2 * 1 = 120。由于阶乘的结果很快就会超出 int64 类型的范围,因此需要使用 big.Int 类型来计算阶乘。
实例9-5:计算大数的阶乘(源码路径:Go-codes\9\jie.go)
实例文件jie.go的具体实现代码如下所示。
import (
"fmt"
"math/big"
)
func factorial(n int) *big.Int {
// 创建一个值为 1 的 big.Int 对象
result := big.NewInt(1)
// 计算 n! 的值
for i := 2; i <= n; i++ {
result.Mul(result, big.NewInt(int64(i)))
}
// 返回计算结果
return result
}
func main() {
// 计算 50 的阶乘
n := 50
fmt.Printf("%d! = %v\n", n, factorial(n))
}
对上述代码的具体说明如下:
- 首先定义了函数factorial(),用于计算给定正整数的阶乘。函数factorial()接受一个 int 类型的参数 n,表示要计算的阶乘数。在函数factorial()内部,首先通过函数big.NewInt()创建一个初始值为 1 的 big.Int 对象,并使用函数Mul()来不断地将其乘以 2, 3, ..., n,最终得到 n! 的值。
- 在主函数main()中,我们调用了函数factorial()来计算 50! 的值,并使用 %v 输出格式符将结果输出到控制台。需要注意的是,由于 50! 的结果非常大,因此输出结果可能需要一些时间才能显示完整。
执行后会输出:
50! = 30414093201713378043612608166064768844377641568960512000000000000
这是一个极大的数字,表示50! 的精确值,由于使用了 big.Int 类型进行计算,因此可以保证计算结果的精度和正确性。这个例子虽然简单,但是展示了包 big 高精度计算的强大功能。除了计算阶乘,big 包还可以用于计算分数、浮点数等任意长度的数学计算。