Go 数据类型篇(二):布尔类型、整型、浮点型和复数类型

您所在的位置:网站首页 Go类型推导 Go 数据类型篇(二):布尔类型、整型、浮点型和复数类型

Go 数据类型篇(二):布尔类型、整型、浮点型和复数类型

2024-02-25 15:20| 来源: 网络整理| 查看: 265

Go 支持的数据类型

Go 语言内置对以下这些基本数据类型的支持:

布尔类型:bool整型:int8、byte、int16、int、uint、uintptr 等浮点类型:float32、float64复数类型:complex64、complex128字符串:string字符类型:rune错误类型:error

此外,Go 语言还支持以下这些复合类型:

指针(pointer)数组(array)切片(slice)字典(map)通道(chan)结构体(struct)接口(interface)

与其他静态语言不同的是,Go 新增了一个通道类型,该类型主要用于并发编程时不同协程之间的通信,后面介绍 Go 语言并发编程的时候会详细介绍它。

结构体类似于面向对象编程语言中的类(class),Go 沿用了 C 语言的这一复合类型,而没有像传统面向对象编程那样引入单独的类概念,Go 语言还把接口单独作为一个类型提出来,后面介绍 Go 语言面向对象编程的时候会详细介绍这两个类型的使用。

下面我们就来逐一介绍这些数据类型。

布尔类型

Go 语言中的布尔类型与其他主流编程语言差不多,类型关键字为 bool,可赋值且只可以赋值为预定义常量 true 和 false。示例代码如下:

var v1 bool v1 = true v2 := (1 == 2) // v2 也会被推导为 bool 类型

Go 是强类型语言,变量类型一旦确定,就不能将其他类型的值赋值给该变量,因此,布尔类型不能接受其他类型的赋值,也不支持自动或强制的类型转换。以下的示例是一些错误的用法,会导致编译错误:

var b bool b = 1 // 编译错误 b = bool(1) // 编译错误

不过通过表达式计算得到的布尔类型结果可以赋值给 Go 布尔类型变量:

var b bool b = (1!=0) // 编译正确 fmt.Println("Result:", b) // 打印结果为Result: true

此外,由于强类型的缘故,Go 语言在进行布尔值真假判断时,对值的类型有严格限制,在 PHP 这种弱类型语言中,以下这些值在进行布尔值判断的时候(使用非严格的 == 比较符)都会被认为是 false(JavaScript、Python 也类似):

布尔值 FALSE 本身整型值 0(零)浮点型值 0.0(零)空字符串,以及字符串 "0"不包括任何元素的数组特殊类型 NULL(包括尚未赋值的变量)从空标记生成的 SimpleXML 对象

而在 Go 语言中则不然,不同类型的值不能使用 == 或 != 运算符进行比较,在编译期就会报错,比如下面这段代码:

b := (false == 0);

在编译的时候就会报如下错误:

cannot convert 0 (type untyped number) to type bool invalid operation: false == 0 (mismatched types bool and int)

同样,! 运算符也不能作用于非布尔类型值。

整型

整型是所有编程语言里最基础的数据类型,Go 语言默认支持如下这些整型类型:

类型

长度(单位:字节)

说明

值范围

默认值

int8

1

带符号8位整型

-128~127

0

uint8

1

无符号8位整型,与 byte 类型等价

0~255

0

int16

2

带符号16位整型

-32768~32767

0

uint16

2

无符号16位整型

0~65535

0

int32

4

带符号32位整型,与 rune 类型等价

-2147483648~2147483647

0

uint32

4

无符号32位整型

0~4294967295

0

int64

8

带符号64位整型

-9223372036854775808~9223372036854775807

0

uint64

8

无符号64位整型

0~18446744073709551615

0

int

32位或64位

与具体平台相关

与具体平台相关

0

uint

32位或64位

与具体平台相关

与具体平台相关

0

uintptr

与对应指针相同

无符号整型,足以存储指针值的未解释位

32位平台下为4字节,64位平台下为8字节

0

Go 支持的整型类型非常丰富,你可以根据需要设置合适的整型类型,以节省内存空间,此外 int 和 int32 在 Go 语言里被认为是两种不同的类型(同理,int 和 int64 也是不同的类型),编译器也不会帮你自动做类型转换,比如以下的例子会有编译错误:

var intValue1 int8 intValue2 := 8 // intValue2 将会被自动推导为 int 类型 intValue1 = intValue2 // 编译错误

编译错误类似于:

cannot use intValue2 (type int) as type int8 in assignment

使用强制类型转换可以解决这个编译错误:

intValue1 = int8(intValue2)) // 编译通过

注:关于类型转换我们在后面介绍完所有数据类型后会单独介绍。

我们还可以通过 intValue := uint8(intValue2) 这种方式同时完成类型转化和赋值操作。

此外,和其他编程语言一样,可以通过增加前缀 0 来表示八进制数(如:077),增加前缀 0x 来表示十六进制数(如:0xFF),以及使用 E 来表示 10 的连乘(如:1E3 = 1000)。

运算符算术运算符

Go 语言支持所有常规的整数四则运算:+、-、*、/ 和 %(取余运算只能用于整数),不过由于强类型的关系,在 Go 语言中,不同类型的整型值不能直接进行算术运算,比如下面这样计算就会报编译错误:

intValue3 := intValue1 + intValue2

编译错误信息如下:

invalid operation: intValue1 + intValue2 (mismatched types int8 and int)

类型转化之后就好了:

intValue3 := intValue1 + int8(intValue2)

如果你是从动态语言转过来学习 Go,在刚开始写代码时尤其要注意这些因为类型问题产生的 bug。

在 Go 语言中,也支持自增/自减运算符,即 ++/--,但是只能作为语句,不能作为表达式,且只能用作后缀,不能放到变量前面:

intValue1++ // 有效,intValue1 的值变成 9 intValue1 = intValue1++ // 无效,编译报错 --intValue1 // 无效,编译报错

还支持 +=、-=、*=、/=、%= 这种快捷写法:

intValue1 += intValue1 // 18 intValue1 -= intValue1 // 0 intValue1 *= intValue1 // 81 intValue1 /= intValue1 // 1 intValue1 %= intValue1 // 0 比较运算符

Go 语言支持以下几种常见的比较运算符:>、=、 y

右移

把 x 中的位向右移动 y 次,每次移动相当于除以 2

我们可以做一些简单的测试:

var intValueBit uint8 intValueBit = 255 intValueBit = ^intValueBit // 按位取反 fmt.Println(intValueBit) // 0 intValueBit = 1 intValueBit = intValueBit ;; 3 // 左移 3 位,相当于乘以 2^3 = 8 fmt.Println(intValueBit) // 8 逻辑运算符

Go 语言支持以下逻辑运算符:

运算符

含义

结果

x && y

逻辑与运算符(AND)

如果 x 和 y 都是 true,则结果为 true,否则结果为 false

x || y

逻辑或运算符(OR)

如果 x 或 y 是 true,则结果为 true,否则结果为 false

!x

逻辑非运算符(NOT)

如果 x 为 true,则结果为 false,否则结果为 true

逻辑运算符计算的结果也是布尔值,通常我们可以组合使用逻辑运算符和比较运算符:

if intValue1 ; intValue3 ;; intValue1 == 8 { fmt.Println("条件为真") } 运算符优先级

上面介绍的 Go 语言运算符优先级如下所示(由上到下表示优先级从高到低,或者数字越大,优先级越高):

6 ^(按位取反) ! 5 * / % > & &^ 4 + - | ^(按位异或) 3 == != < >= 2 && 1 ||

++ 或 -- 只能出现在语句中,不能用于表达式,故不参与优先级判断。

浮点型

浮点型也叫浮点数,用于表示包含小数点的数据,比如 3.14、1.00 都是浮点型数据。

浮点数的表示

Go 语言中的浮点数采用IEEE-754 标准的表达方式,定义了两个类型:float32 和 float64,其中 float32 是单精度浮点数,可以精确到小数点后 7 位(类似 PHP、Java 等语言的 float 类型),float64 是双精度浮点数,可以精确到小数点后 15 位(类似 PHP、Java 等语言的 double 类型)。

在 Go 语言里,定义一个浮点型变量的代码如下:

var floatValue1 float32 floatValue1 = 10 floatValue2 := 10.0 // 如果不加小数点,floatValue2 会被推导为整型而不是浮点型 floatValue3 := 1.1E-10

对于浮点类型需要被自动推导的变量,其类型将被自动设置为 float64,而不管赋值给它的数字是否是用 32 位长度表示的。因此,对于以上的例子,下面的赋值将导致编译错误:

floatValue1 = floatValue2 // floatValue2 是 float64 类型

编译错误信息如下:

cannot use floatValue2 (type float64) as type float32 in assignment

必须使用这样的强制类型转换才可以:

floatValue1 = float32(floatValue2)

在实际开发中,应该尽可能地使用 float64 类型,因为 math 包中所有有关数学运算的函数都会要求接收这个类型。

浮点数的精度

浮点数不是一种精确的表达方式,因为二进制无法精确表示所有十进制小数,比如 0.1、0.7 这种,下面我们通过一个示例来给大家直观演示下:

floatValue4 := 0.1 floatValue5 := 0.7 floatValue6 := floatValue4 + floatValue5

注:浮点数的运算和整型一样,也要保证操作数的类型一致,float32 和 float64 类型数据不能混合运算,需要手动进行强制转化才可以,这一点和动态语言不同。

你觉得上面计算结果 floatValue6 的值是多少?0.8?不,它的结果是 0.7999999999999999,这是因为计算机底层将十进制的 0.1 和 0.7 转化为二进制表示时,会丢失精度,所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。

浮点数的比较

浮点数支持通过算术运算符进行四则运算,也支持通过比较运算符进行比较(前提是运算符两边的操作数类型一致),但是涉及到相等的比较除外,因为我们上面提到,看起来相等的两个十进制浮点数,在底层转化为二进制时会丢失精度,因此不能被表象蒙蔽。

如果一定要判断相等,下面是一种替代的解决方案:

p := 0.00001 // 判断 floatValue1 与 floatValue2 是否相等 if math.Dim(float64(floatValue1), floatValue2) ; p { fmt.Println("floatValue1 和 floatValue2 相等") }

可以看到,我们的解决方案是一种近似判断,通过一个可以接受的最小误差值 p,约定如果两个浮点数的差值在此精度的误差范围之内,则判定这两个浮点数相等。这个解决方案也是其他语言判断浮点数相等所采用的通用方案。

复数类型

除了整型和浮点型之外,Go 语言还支持复数类型,与复数相对,我们可以把整型和浮点型这种日常比较常见的数字称为实数,复数是实数的延伸,可以通过两个实数(在计算机中用浮点数表示)构成,一个表示实部(real),一个表示虚部(imag),常见的表达形式如下:

z = a + bi

其中 a、b 均为实数,i 称为虚数单位,当 b = 0 时,z 就是常见的实数,当 a = 0 而 b ≠ 0 时,将 z 称之为纯虚数,如果你理解数学概念中的复数概念,这些都很好理解,下面我们来看下复数在 Go 语言中的表示和使用。

在 Go 语言中,复数支持两种类型:complex64(32 位实部和虚部) 和 complex128(64 位实部与虚部),对应的表示示例如下,和数学概念中的复数表示形式一致:

var complexValue1 complex64 complexValue1 = 1.10 + 10i // 由两个 float32 实数构成的复数类型 complexValue2 := 1.10 + 10i // 和浮点型一样,默认自动推导的实数类型是 float64,所以 complexValue2 是 complex128 类型 complexValue3 := complex(1.10, 10) // 与 complexValue2 等价

对于一个复数 z = complex(x, y),就可以通过 Go 语言内置函数 real(z) 获得该复数的实部,也就是 x,通过 imag(z) 获得该复数的虚部,也就是 y。

复数支持和其它数字类型一样的算术运算符。当你使用 == 或者 != 对复数进行比较运算时,由于构成复数的实数部分也是浮点型,需要注意对精度的把握。

更多关于复数的函数,请查阅 math/cmplx 标准库的文档。如果你对内存的要求不是特别高,最好使用 complex128 作为计算类型,因为相关函数大都使用这个类型的参数。

(本文完)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3