Golang 的基本数据类型

2019-10-11 15:04:12   最后更新: 2019-10-11 16:53:50   访问数量:58




上一篇文章中,我们介绍了 golang 的程序结构:

GoLang 程序结构

 

如果说程序结构与流程控制是程序的骨架,那么数据就是程序的血肉,所以本文我们就来介绍一下 golang 中的数据类型

 

 

golang 中的数据类型主要分为四大类:

  1. 基础类型
  2. 聚合类型
  3. 引用类型
  4. 接口类型

 

基础类型

基础类型包括下面几种数据类型:

  1. 数字
  2. 字符串
  3. 布尔型

 

聚合类型

聚合类型是通过各种类型组合而成的数据类型,有两种:

  1. 数组
  2. slice
  3. map
  4. 结构体

 

引用类型

引用类型是一种间接指向程序变量或状态的类型,包括:

  1. 指针
  2. 函数
  3. 通道

 

本文我们先来介绍一下 golang 的基础数据类型

 

golang 中,整数类型包括:

  • int8(-128 -> 127,别名 byte)
  • int16(-32768 -> 32767)
  • int32(-2,147,483,648 -> 2,147,483,647)
  • int64(-9,223,372,036,854,775,808 -> 9,223,372,036,854,775,807)
  • int(占用位数取决于具体的实现,在同一个平台上,不同的编译器可能是不同的,别名 rune)
  • uint8(0 -> 255)
  • uint16(0 -> 65,535)
  • uint32(0 -> 4,294,967,295)
  • uint64(0 -> 18,446,744,073,709,551,615)
  • uint (占用位数取决于具体的实现)
  • uintptr(无符号整型,用于保存指针,占用位数依赖于具体实现,但保证可以完整保存指针)

 

所有上述类型都是不同的类型,如果需要比较或运算操作,都必须显式转换

虽然 intxx/uintxx 类型的 xx 表明了 int 型占用的位长度,但最为常用的仍然是长度依赖于不同实现的 int 型

 

无符号整数可能带来的问题

即使你在业务中某个数取值不会小于 0,仍然建议使用 int 而不是 uint,因为例如下面的程序:

var initval uint = 8 for i := initval; i >= 0; i-- { // loop body }

 

 

上述代码将陷入死循环,因为 i := initval 声明了新变量 i,i 的类型与 initval 相同是 uint 类型,而他永远不会减到 0 以下,这样的问题很难察觉

无符号整数通常只用于位运算和特定算数运算符,如散列和加密

 

golang 中有两种浮点型:

  1. float32(+- 1.4 * 1e-45 -> +- 3.4 * 1e38)
  2. float64(+- 4.9 * 1e-324 -> 1.8 * 1e308)

 

上面科学计数法的方式看上去很不直观,换句话说,十进制下,float32 有效数字大约有 6 位,float64 有效数字大约有 15 位,因此大多情况下推荐使用 float64

 

IEEE 754 标准定义了一个特殊值 -- NaN(Not a Number),用来表示超出最大许可值的数以及除以 0 的商

他通过标准库 math 包来创建:

nan := math.NaN()

 

 

基于 NaN 的所有比较都会返回 false,即使是 nan == nan 也会返回 false

 

布尔型 boolean 只有两种取值:true 和 false,但他们不能在其他类型间进行强制类型转换,这与大部分语言中是不同的

可以通过下面的代码进行转换:

boolean 转换为 0 或 1

func btoi(b bool) int { if b { return 1 } return 0 }

 

 

0 或 1 转换为 bool

func itob(i int) bool { return i != 0 }

 

 

字符串是不可变字节序列,这意味着对于 s := "hello world",你可以通过 s[0]、s[6] 获取字符 'h' 和 'w',但对相应位置的赋值 s[0] = 'y' 会造成编译出错

 

golang 中,用 const 关键字定义常量:

const pi = 3.14159 const ( e = 2.71828 pi = 3.14159 )

 

 

常量的赋值语句是在编译期计算出值的,在执行过程中不能进行修改,因此常量必须有初始化语句或赋值

如果声明一组常量,除了第一项之外,其他项可以省略赋值语句,编译器会自动以第一项的数据和类型初始化这些缺省的常量:

const ( a = 1 b c = 2 d ) fmt.Println(a, b, c, d)

 

 

打印出了 1 1 2 2

 

golang 中的枚举

我们了解了常量的创建方法,就可以通过一个集合来创建一系列常量的集合,这非常类似于其他语言中的枚举类型

golang 还提供了用于生成递增初始值的关键字 iota:

package main func main() { const ( Sunday = iota Monday Tuesday Wednesday Thursday Friday Saturday ) print(Tuesday) }

 

 

打印出了 2,iota 会让接下来同组的其他缺省初始值的常量具有递增的初始值

iota 还可以参与基本的运算:

const ( _ = 1 << (10 * iota) KiB // 1024 MiB // 1048576 GiB // 1073741824 TiB // 1099511627776 (超过了int32的范围) PiB // 1125899906842624 EiB // 1152921504606846976 ZiB // 1180591620717411303424 (超过了int64的范围) YiB // 1208925819614629174706176 )

 

 

但是这存在很大的局限性,因为常量的分配和赋值是在编译期进行的,因此不能通过调用函数来实现常量的赋值,因此复杂的运算甚至条件、循环都不能用在这里,例如,如果我们要取 K、M、G 这样以 1000 为单位累乘的结果时,iota 就显得力不从心了

const ( K = 1000 M = 1000 * K G = 1000 * M T = 1000 * G P = 1000 * T )

 

 

欢迎关注微信公众号,以技术为主,涉及历史、人文等多领域的学习与感悟,每周三到七篇推文,只有全部原创,只有干货没有鸡汤

 

 






array      golang      go      int      float      数组     


京ICP备15018585号