您的位置 首页 golang

网络工程师的Golang之路 — Go数据类型(数字型)

版权声明:我已加入“维权骑士”( )的版权保护计划,知乎专栏“网路行者”下的所有文章均为我本人(知乎ID:弈心)原创,未经允许不得转载。

如果你喜欢我的文章,请关注我的知乎专栏“网路行者” , 里面有更多像本文一样深度讲解计算机网络技术的优质文章。


Go 中数字型数据类型大致分为整数( integer )、 浮点数 (floating point )和复数(Complex)三种,其中 复数 网络工程师 的日常工作关系不大,这里只介绍整数和浮点数。

整数重要概念

  • 整数在Go和Python中有较大区别,主要体现在Go对整数的划分更细。Go中同时提供了 有符号(signed) 无符号( unsigned 的整数类型,其中有符号整数按 二进制 位又可以分为int8(对应8bit大小的有符号整数),int16(对应16bit大小的有符号整数),int32(对应32bit大小的有符号整数),int64(对应64bit大小的有符号整数),以及int(与CPU平台相关)五种类型。无符号整数按二进制位又可以分为uint8, uint16, uint32, uint64以及uint五种类型。
  • 根据二进制大小的不同,每种有符号整数和无符号整数类型所代表的整数范围也不尽相同,如下表所示:

有符号整数类型

大小

整数范围

int8

8 bits

-128 到 127

int16

16
bits

-215 到 215-1

int32

32
bits

-231 到 231-1

int64

64
bits

-263 到 263-1

int

编译器、CPU相关

编译器、CPU相关

无符号整数类型

大小

整数范围

uint8

8 bits

0 到 255

uint16

16
bits

0 到 216 -1

uint32

32
bits

0 到 232 -1

uint64

64
bits

0 到 264 -1

uint

编译器、CPU相关

编译器、CPU相关

  • 有符号整数和无符号整数的最大的区别是前者支持负数,后者不支持。 另外int这个整数类型我们在前面讲解变量时所举的例子中已经提及并使用过了,它的大小与所代表的整数范围和运行Go程序的机器的编译器和CPU相关(既可能是32bit也可能是64bit,uint同理)。实际开发中int类型的应用最为广泛,它既可用于数组和切片的 索引 ,也可用于for循环中空值循环次数的计数器,而且一般来说int类型的处理速度也是最快的,所以通常情况下我们在创建整数变量时直接声明int这个有符号整数类型的变量就足够应付网络工程师所有日常的网络运维自动化工作了。
  • 除int和uint之外,还有一个大小及所代表的整数范围和编译器及CPU相关的整数数据类型叫做uintptr,它只在Go语言和C语言之间互动的底层编程中才会用到,不是网络工程师需要掌握的知识点。

整数使用举例

整数支持加减乘除、取模等操作,但前提是变量的整数类型必须一致,并且数字不能超出该类型的整数范围,举例如下:

 package main
 
import "fmt"
 
func main() {
    var a, b int = 7, 2
    fmt.Println(a + b)
    fmt.Println(a - b)
    fmt.Println(a * b)
    fmt.Println(a / b)
}
  

这里注意Go中当两个整数不能整除时,只保留商数,因此7/2返回的值为3。

如果变量的整数类型不一致,则系统会返回异常,举例如下:

 package main

 import  (
 "fmt"
)

func main() {
    var a int8 = 1
    var b uint8 = 1
    fmt.Println(a + b)
}
  

这里变量a的数据类型为int8,而b的数据类型为uint8,两者无法做任何运算。

如果数字超出了数据类型对应的整数范围,则系统也会返回异常,举例如下:

 package main

import (
 "fmt"
)

func main() {
    var a int8 = 256
    fmt.Println(a)
}
  

这里变量a的值256超出了int8对应的支持范围(-128到127)。


浮点数

浮点数用来表示带有小数点的数字,比如1.0,-45.332。在Go中 浮点 数分为 float 32和float64两种类型,两种类型代表了两种精度,它们都严格参照 IEEE 754 的标准,即IEEE Standard for Floating-Point Arithmetic(IEEE浮点数算术标准)。

float32 vs float64

float32类型的浮点数和float64类型的浮点数两者区别在于前者为单精度浮点数,可以提供约6个十进制数的精度,在内存中占用32个bits,而后者为双精度浮点数,可以提供约15个十进制数的精度,在内存中占用64个bits。

怎么具体来理解这两者的区别呢?举个例子:

 package main

import "fmt"

func main() {
    var f1 float32 = 16777216
    fmt.Println(f1 == f1 + 1)
    var f2 float64 = 16777216
    fmt.Println(f2 == f2 + 1)
}
  

这里我们用float32和float64分别创建了两个变量f1和f2,它们的值都为16777216(整数同样可以赋值给浮点数类型的变量),但是如果给它们各自加上1后再用==做判断,可以看到类型为float32的变量f1 == f1+1返回了 布尔 值true,类型为float64的变量f2 == f2+1返回了布尔值false。其原因是因为在IEEE 754标准中,32位的浮点数其构成为:

Value = (sign ? -1 : +1) * 2^exponent * (1.0 + mantissa)

  • Value即为浮点数的值
  • 1个bit用于符号位 (sign bit),符号位用来判断判断正数或负数(+1表示正数,-1表示负数)
  • 8个bit用于指数(exponent,带有-127的偏移)
  • 23个bit用于尾数 (mantissa)

可以看到16777216对应的是224,如果用float32来表示的话:

  • 符号位(sign bit) = +1 (表示正数)
  • 指数 = 24 (保存在内存中的二进制为10010111,这个10010111是从24 + 127(指数偏移) = 151=10010111得来的)
  • 尾数 = .0(即小数点后的小数为0)

因此 Value = (+1) x 224 x (1.0 + .0) = 16777216

再来看16777217,也就是224+1:

  • 符号位和指数不变
  • 尾数必须为2-24 因为只有这样Value才会= (+1) x 224 x (1.0 + 2-24) = 16777217
  • 但是因为尾数位只有23bit,因此用float32是无法表示16777217的。 在float32中,16777217会以16777216表示,不会以16777218表示,这涉及到向最近的值舍入(round to nearest)的知识点,该知识点不在本书的讨论范围内。

由此可以看出float32能精确表示的正整数并不是很大,所以通常我们用float64来声明浮点数变量。不过使用float64也就意味着程序会占用更大的内存,在深度学习这种需要大量使用数据集的领域,占用内存的多少会对系统运行效率有较为明显的影响。但是对网络工程师来说,我们日常工作中通常不会和大量数据打交道,因此不用担心这点。


整数和 字符串 互相转换

整数转换为字符串

整数转换为字符串大致有三种方法:

  1. 使用string()
  2. 使用 strconv .ItoA()
  3. 使用strconv.Format()

第一种使用string()的方法和后面两种使用strconv包的方法有本质上的区别。对整数使用string()函数的话,其返回的值不是字符串形式的整数,而是该整数对应的字符rune,举例如下:

 package main
 
import (
 "fmt"
)
 
func main() {
    num := 100
    fmt.Println(string(num))
}
  

可以看到对整数100使用string()并未将其转化为字符串形式的整数”100″,而是该整数对应的字符”d”。这时你也会发现VS Code中的脚本名称变为了黄色,表示有提示,打开PROBLEMS一栏可以看到“conversion from int to string yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)”的提示,正好对应我们遇到的这种情况。

如果你的目的是将一个整数转换为该整数的字符串形式,则需要使用strconv.ItoA()或者strconv.Format(),举例如下:

 package main
 
import (
 "fmt"
 "strconv"
)
 
func main() {
    num := 100
    fmt.Println(strconv.Itoa(num))
    fmt.Println(strconv.FormatInt(int64(num), 10))
}
  

其中strconv.Itoa()函数里的Itoa是Integer to ASCII的缩写,strconv包下的Itoa()是最简易也最常用的将整数转换为字符串的函数,推荐使用。而与strconv.Itoa()相对应的则是strconv.Atoi(),即 ASCII to Integer,表示将字符串转换为整数。

strconv.FormatInt()函数比较严格,要使用的话必须传入两个参数,且第一个参数必须为int64的有符号整数,因为我们创建的变量的数据类型为int,不是int64,因此需要用int64(num)将其转化为int64才能作为合法的参数传入。第二个参数为进制,这里的10表示十进制,如果想用十六进制表达的话,则将10改为16即可,举例如下:

 package main
 
import (
 "fmt"
 "strconv"
)
 
func main() {
    num := 100
    fmt.Println(strconv.Itoa(num))
    fmt.Println(strconv.FormatInt(int64(num), 16))
}
  

可以看到10进制的100转换成16进制的话为64,不过注意这里打印出来的这个“64”的数据类型为字符串,不是整数。

字符串转换为整数:

字符串转换为整数大致两种方法,除了前面提到的strconv.Atoi()外,也可以用strconv.ParseInt()来完成。

先举例讲讲strconv.Atoi(),因为它有些特殊:

 package main
 
import (
 "fmt"
 "strconv"
)
 
func main() {
    str := "100"
    fmt.Println(strconv.Atoi(str))
}
  

这里可以看到,对字符串变量str使用strconv.Atoi()后,返回的值为100 <nil>,为什么会有两个值?这是因为strconv.Atoi()函数本身默认会返回两个值,第一个值的数据类型为整数,第二个值的数据类型为error,我在讲字符串一章中提到了错误类型在Go中也属于一种数据类型,如果调用该函数时存在错误的话,比如被strconv.Atoi()转换的数据为非字符串,那么strconv.Atoi()会返回具体的错误类型,如果函数运行后不存在错误的话,则返回 nil 。在Go中类似strconv.Atoi()这种同时返回两种值(一种为函数本身因返回的值,另一种为错误类型的值)的函数还有很多,后面会慢慢讲到。

接下来再来看strconv.ParseInt()的使用:

 package main
 
import (
 "fmt"
 "strconv"
)
 
func main() {
    str := "100"
    fmt.Println(strconv.ParseInt(str, 10, 64))
}
  

可以看到,strconv.ParseInt()需要传入三个参数,一个参数为要被转换为整数的字符串,第二个参数为进制,这里的10代表十进制,第三个参数代表的是bitSize, 其作用是用来指定我们想将字符串转换为哪类的有符号整数类型,其取值范围为0,8,16,32,64,分别表示int, int8, int16,int32和int64。

Strconv.FormatInt()和strconv.ParseInt()功能比较强大,但是使用起来稍微有些繁琐,明显strconv.Itoa()和strconv.Atoi()更易用。实际上strconv.Itoa()和strconv.Atoi()其实分别调用了strconv.Format()和strconv.ParseInt(),是后两者的简化版,对我们网络工程师来说,Atoi和Itoa更常用。

另外Format和Parse其实是两组相反的方法,除了strconv.FormatInt()和strconv.ParseInt()外还有如下很多种类似的函数:

Format组:

FormatBool()

FormatFloat()

FormatInt()

FormatUint()

Parse组:

ParseBool()

ParseFloat ()

ParseInt ()

ParseUint()

总体来说,Format组是将其他数据类型转变成字符串,而Parse组是将字符串转为其他数据类型。

文章来源:智云一二三科技

文章标题:网络工程师的Golang之路 — Go数据类型(数字型)

文章地址:https://www.zhihuclub.com/86514.shtml

关于作者: 智云科技

热门文章

网站地图