前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go 数据类型篇(二):布尔类型、整型、浮点型和复数类型

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

作者头像
学院君
发布2023-03-03 13:45:40
1.3K0
发布2023-03-03 13:45:40
举报
文章被收录于专栏:学院君的专栏

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,可赋值且只可以赋值为预定义常量 truefalse。示例代码如下:

代码语言:javascript
复制
var v1 bool 
v1 = true 
v2 := (1 == 2) // v2 也会被推导为 bool 类型

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

代码语言:javascript
复制
var b bool 
b = 1 // 编译错误 
b = bool(1) // 编译错误

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

代码语言:javascript
复制
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 语言中则不然,不同类型的值不能使用 ==!= 运算符进行比较,在编译期就会报错,比如下面这段代码:

代码语言:javascript
复制
b := (false == 0);

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

代码语言:javascript
复制
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 支持的整型类型非常丰富,你可以根据需要设置合适的整型类型,以节省内存空间,此外 intint32 在 Go 语言里被认为是两种不同的类型(同理,intint64 也是不同的类型),编译器也不会帮你自动做类型转换,比如以下的例子会有编译错误:

代码语言:javascript
复制
var intValue1 int8
intValue2 := 8   // intValue2 将会被自动推导为 int 类型 
intValue1 = intValue2  // 编译错误

编译错误类似于:

代码语言:javascript
复制
cannot use intValue2 (type int) as type int8 in assignment

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

代码语言:javascript
复制
intValue1 = int8(intValue2)) // 编译通过

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

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

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

运算符

算术运算符

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

代码语言:javascript
复制
intValue3 := intValue1 + intValue2

编译错误信息如下:

代码语言:javascript
复制
invalid operation: intValue1 + intValue2 (mismatched types int8 and int)

类型转化之后就好了:

代码语言:javascript
复制
intValue3 := intValue1 + int8(intValue2)

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

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

代码语言:javascript
复制
intValue1++  // 有效,intValue1 的值变成 9
intValue1 = intValue1++ // 无效,编译报错
--intValue1  // 无效,编译报错

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

代码语言:javascript
复制
intValue1 += intValue1 // 18
intValue1 -= intValue1 // 0
intValue1 *= intValue1 // 81
intValue1 /= intValue1 // 1
intValue1 %= intValue1 // 0

比较运算符

Go 语言支持以下几种常见的比较运算符:><==>=<=!=,比较运算符运行的结果是布尔值。

如前面所说,Go 是强类型语言,不同类型的值不能放在一起比较,否则会报编译错处:

代码语言:javascript
复制
if intValue1 == intValue2 {
    fmt.Println("intValue1 和 intValue2 相等")
}

相同类型的值才可以:

代码语言:javascript
复制
if intValue1 &lt; intValue3 {
    fmt.Println("intValue1 比 intValue3 小")
}

由此可见,所有比较运算符在比较的时候都会考虑进数据类型的因素,所以不需要额外引入类似 PHP 等动态语言中的 ===!== 这种严格比较运算符。

不过,各种类型的整型变量都可以直接与字面常量进行比较,比如:

代码语言:javascript
复制
if intValue1 == 8 {
    fmt.Println("intValue1 = 8")
}

位运算符

位运算符以二进制的方式对数值进行运算,效率更高,性能更好,Go 语言支持以下这几种位运算符:

运算符

含义

结果

x & y

按位与

把 x 和 y 都为 1 的位设为 1

x | y

按位或

把 x 或 y 为 1 的位设为 1

x ^ y

按位异或

把 x 和 y 一个为 1 一个为 0 的位设为 1

^x

按位取反

把 x 中为 0 的位设为 1,为 1 的位设为 0

x << y

左移

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

x >> y

右移

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

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

代码语言:javascript
复制
var intValueBit uint8
intValueBit = 255
intValueBit = ^intValueBit // 按位取反
fmt.Println(intValueBit)   // 0
intValueBit = 1
intValueBit = intValueBit &lt;&lt; 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

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

代码语言:javascript
复制
if intValue1 &lt; intValue3 &amp;&amp; intValue1 == 8 {
    fmt.Println("条件为真")
}

运算符优先级

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

代码语言:javascript
复制
6      ^(按位取反) !
5      *  /  %  <<  >>  &  &^
4      +  -  |  ^(按位异或)
3      ==  !=  <  <=  >  >=
2      &&
1      ||

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

浮点型

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

浮点数的表示

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

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

代码语言:javascript
复制
var floatValue1 float32

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

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

代码语言:javascript
复制
floatValue1 = floatValue2  // floatValue2 是 float64 类型

编译错误信息如下:

代码语言:javascript
复制
cannot use floatValue2 (type float64) as type float32 in assignment

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

代码语言:javascript
复制
floatValue1 = float32(floatValue2)

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

浮点数的精度

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

代码语言:javascript
复制
floatValue4 := 0.1
floatValue5 := 0.7
floatValue6 := floatValue4 + floatValue5

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

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

浮点数的比较

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

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

代码语言:javascript
复制
p := 0.00001
// 判断 floatValue1 与 floatValue2 是否相等
if math.Dim(float64(floatValue1), floatValue2) &lt; p {
    fmt.Println("floatValue1 和 floatValue2 相等")
} 

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

复数类型

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

代码语言:javascript
复制
z = a + bi

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

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

代码语言:javascript
复制
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 作为计算类型,因为相关函数大都使用这个类型的参数。

(本文完)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 极客书房 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Go 支持的数据类型
  • 布尔类型
  • 整型
  • 运算符
    • 算术运算符
      • 比较运算符
        • 位运算符
          • 逻辑运算符
            • 运算符优先级
            • 浮点型
              • 浮点数的表示
                • 浮点数的精度
                  • 浮点数的比较
                  • 复数类型
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档