浮点型用于表示包含小数点的数据,比如1.234就是一个浮点型数据。Go语言中的浮点类型采用IEEE-754
标准的表达方式。
(1)浮点数表示Go语言定义了两个类型 float32 和 float64 ,其中 float32 等价于C语言的 float 类型,
float64 等价于C语言的 double 类型。
在Go语言里,定义一个浮点数变量的代码如下:fvalue2 := 12.0 // 如果不加小数点,fvalue2会被推导为整型而不是浮点型
对于以上例子中类型被自动推导的 fvalue2 ,需要注意的是其类型将被自动设为 float64 ,而不管赋给它
的数字是否是用32位长度表示的。因此,对于以上的例子,下面的赋值将导致编译错误:
fvalue1 = fvalue
而必须使用这样的强制类型转换:fvalue1 = float32(fvalue2)
(2)浮点数比较
因为浮点数不是一种精确的表达方式,所以像整型那样直接用 == 来判断两个浮点数是否相等
是不可行的,这可能会导致不稳定的结果。
下面是一种推荐的替代方案:
import "math"
func IsEqual(f1, f2, p float64) bool { // p为用户自定义的比较精度,比如0.00001
return math.Fdim(f1, f2) < p
}
3.4 复数类型
复数实际上由两个实数(在计算机中用浮点数表示)构成,一个表示实部(real),一个表示虚部(imag)。
如果了解了数学上的复数是怎么回事,那么Go语言的复数就非常容易理解了。
(1)复数表示
复数表示的示例如下:
var value1 complex64 // 由2个float32构成的复数类型
value1 = 3.2 + 12i
value2 := 3.2 + 12i // value2是complex128类型
value3 := complex(3.2, 12) // value3结果同 value2
(2)实部与虚部
对于一个复数 z = complex(x, y) ,就可以通过Go语言内置函数 real(z) 获得该复数的实部,也就是 x ,
通过 imag(z) 获得该复数的虚部,也就是 y 。
更多关于复数的函数,请查阅 math/cmplx 标准库的文档。
3.5 字符串
在Go语言中,字符串也是一种基本类型。相比之下, C/C++语言中并不存在原生的字符串类型,
通常使用字符数组来表示,并以字符指针来传递。
Go语言中字符串的声明和初始化非常简单,举例如下:
var str string // 声明一个字符串变量
str = "Hello world" // 字符串赋值
ch := str[0] // 取字符串的第一个字符
fmt.Printf("The length of \"%s\" is %d \n", str, len(str))
fmt.Printf("The first character of \"%s\" is %c.\n", str, ch)
输出结果为:
The length of "Hello world" is 11
The first character of "Hello world" is H.
字符串的内容可以用类似于数组下标的方式获取,但与数组不同,字符串的内容不能在初始化后被修改,
比如以下的例子:
str := "Hello world" // 字符串也支持声明时进行初始化的做法
str[0] = 'X' // 编译错误
编译器会报类似如下的错误:
cannot assign to str[0]
在这个例子中我们使用了一个Go语言内置的函数 len() 来取字符串的长度。这个函数非常有
用,我们在实际开发过程中处理字符串、数组和切片时将会经常用到。
本节中还顺便示范了 Printf() 函数的用法。有C语言基础的读者会发现, Printf() 函
数的用法与C语言运行库中的 printf() 函数如出一辙。在以后学习更多的Go语言特性时,
可以配合使用 Println() 和 Printf() 来打印各种自己感兴趣的信息。
Go编译器支持UTF-8的源代码文件格式。这意味着源代码中的字符串可以包含非ANSI的字
符,比如“Hello world. 你好,世界!”可以出现在Go代码中。但需要注意的是,如果Go代
码需要包含非ANSI字符,保存源文件时请注意编码格式必须选择UTF-8。特别是在Windows下一
般编辑器都默认存为本地编码,比如中国地区可能是GBK编码而不是UTF-8,如果没注意这点在
编译和运行时就会出现一些意料之外的情况。
字符串的编码转换是处理文本文档(比如TXT、XML、HTML等)非常常见的需求,不过可
惜的是Go语言仅支持UTF-8和Unicode编码。对于其他编码,Go语言标准库并没有内置的编码转
换支持。不过,所幸的是我们可以很容易基于 iconv 库用Cgo包装一个。这里有一个开源项目:
https://github.com/xushiwei/go-iconv,这个开源项目在书上看到的,还没怎么研究看。
(1)字符串操作
平时常用的字符串操作如表2-3所示。
更多的字符串操作,请参考标准库 strings 包。
(2) 字符串遍历
Go语言支持两种方式遍历字符串。一种是以字节数组的方式遍历:
str := "Hello,世界"
n := len(str)
for i := 0; i < n; i++ {
ch := str[i] // 依据下标取字符串中的字符,类型为byte
fmt.Println(i, ch)
}
这个例子的输出结果为:
0 72
1 101
2 108
3 108
4 111
5 44
6 32
7 228
8 184
9 150
10 231
11 149
12 140
可以看出,这个字符串长度为13。尽管从直观上来说,这个字符串应该只有9个字符。这是
因为每个中文字符在UTF-8中占3个字节,而不是1个字节。另一种是以Unicode字符遍历:
str := "Hello,世界"
for i, ch := range str {
fmt.Println(i, ch)//ch的类型为rune
}
输出结果为:
0 72
1 101
2 108
3 108
4 111
5 44
6 32
7 19990
10 30028
以Unicode字符方式遍历时,每个字符的类型是 rune (早期的Go语言用 int 类型表示Unicode
字符),而不是 byte 。
3.6 字符类型
在Go语言中支持两个字符类型,一个是 byte (实际上是 uint8 的别名),代表UTF-8字符串
的单个字节的值;另一个是 rune ,代表单个Unicode字符。
关于 rune 相关的操作,可查阅Go标准库的 unicode 包。另外 unicode/utf8 包也提供了
UTF8和Unicode之间的转换。
出于简化语言的考虑,Go语言的多数API都假设字符串为UTF-8编码。尽管Unicode字符在标
准库中有支持,但实际上较少使用。