海口免费做网站,信息服务平台怎么赚钱,永久免费微信小程序商城,黄石网站建设定做引言
数据类型指定了编写程序时特定变量存储的值的类型。数据类型还决定了可以对数据执行哪些操作。
在本文中#xff0c;我们将介绍Go的重要数据类型。这不是对数据类型的详尽研究#xff0c;但将帮助您熟悉Go中可用的选项。理解一些基本的数据类型能让你写出更清晰、性能…引言
数据类型指定了编写程序时特定变量存储的值的类型。数据类型还决定了可以对数据执行哪些操作。
在本文中我们将介绍Go的重要数据类型。这不是对数据类型的详尽研究但将帮助您熟悉Go中可用的选项。理解一些基本的数据类型能让你写出更清晰、性能更高效的代码。
背景
理解数据类型的一种方法是考虑我们在现实世界中使用的不同类型的数据。现实世界中数据的一个例子是数字:例如我们可以使用整数(0,1,2…)、整数(…-1,0,1…)和无理数(π)。
通常在数学中我们可以组合不同类型的数字并得到某种答案。我们可能想将π加5例如:
5 π我们可以保留这个方程作为无理数的答案也可以将π四舍五入到一个小数位较少的数字中然后再将它们相加:
5 π 5 3.14 8.14 但是如果我们开始尝试用另一种数据类型(如单词)计算数字就会变得不那么有意义。我们如何解下面的方程?
shark 8对于计算机来说每种数据类型都非常不同就像单词和数字一样。因此我们必须小心如何使用不同的数据类型来赋值以及如何通过操作操作它们。
Integers
与数学一样计算机编程中的整数是整数可以是正、负或0(…- 1,0,1…)。在Go中整数被称为int。与其他编程语言一样在4位或4位以上的数字中不应该使用逗号因此在程序中编写1000时请将其写成1000。
可以像下面这样简单地打印一个整数:
fmt.Println(-459)Output-459或者我们可以声明一个变量在本例中它是我们正在使用或操作的数字的符号如下所示:
var absoluteZero int -459
fmt.Println(absoluteZero)Output-459我们也可以在Go中使用整数进行数学运算。在下面的代码块中我们将使用:赋值操作符来声明和实例化变量sum:
sum : 116 - 68
fmt.Println(sum)Output48如输出所示数学运算符-将116减去整数68得到48。你将在为变量声明数据类型部分了解更多关于变量声明的内容。
在Go程序中整数可以以多种方式使用。随着您继续学习Go您将有很多机会使用整数并在此数据类型的知识基础上进行工作。
浮点数
浮点数或浮点数用于表示不能表示为整数的实数。实数包含所有有理数和无理数因此浮点数可以包含小数部分如9.0或-116.42。为了理解Go程序中的浮点数它是一个包含小数点的数字。
像处理整数一样可以像下面这样简单地打印一个浮点数:
fmt.Println(-459.67)Output-459.67还可以声明一个变量来表示浮点数如下所示:
absoluteZero : -459.67
fmt.Println(absoluteZero)Output-459.67就像整数一样我们也可以在Go中使用浮点数进行数学运算:
var sum 564.0 365.24
fmt.Println(sum)Output929.24对于整数和浮点数重要的是要记住3≠3.0因为3指整数而3.0指浮点数。
数值类型的大小
除了整数和浮点数之间的区别之外Go还有两种类型的数值数据它们的区别在于其大小的静态或动态性质。第一种类型是体系结构无关类型这意味着无论代码在什么机器上运行以位为单位的数据长度都不会改变。
今天的大多数系统体系结构不是32位就是64位。例如你可能正在为一台现代的Windows笔记本电脑开发应用程序其操作系统运行在64位体系结构上。但是如果您正在为健身手表之类的设备开发则可能需要使用32位架构。如果你使用体系结构无关的类型如int32无论你编译的是什么体系结构该类型都将具有固定的大小。
第二种是特定于实现的类型。在这种类型中位长可能因程序所基于的体系结构而异。例如如果我们使用int类型当Go编译为32位体系结构时数据类型的大小将为32位。如果程序是针对64位体系结构编译的则该变量的大小为64位。
除了有不同大小的数据类型像整数这样的数据类型也有两种基本类型:有符号和无符号。int8是一个有符号整数它的值可以是-128到127。uint8是一个无符号整数只能是0 ~ 255的正数。
这些范围是基于位的大小。对于二进制数据8位可以表示256个不同的值。因为int类型需要同时支持正数和负数一个8位整数(int8)的范围是-128到127总共有256个不同的可能值。
Go有以下体系结构无关的整数类型:
uint8 无符号8位整数 (0 to 255)
uint16 无符号16位整数 (0 to 65535)
uint32 无符号32位整数 (0 to 4294967295)
uint64 无符号64位整数 (0 to 18446744073709551615)
int8 带符号的8位整数 (-128 to 127)
int16 带符号的16位整数 (-32768 to 32767)
int32 带符号的32位整数 (-2147483648 to 2147483647)
int64 带符号的64位整数 (-9223372036854775808 to 9223372036854775807)浮点数和复数的大小也各不相同:
float32 IEEE-754 32位浮点数
float64 IEEE-754 64位浮点数
complex64 具有float32类型变量实部和虚部的复数
complex128 具有float64类型变量实部和虚部的复数还有一些别名编号类型可以为特定的数据类型指定有用的名称。
byte uint8的别名
rune int32的别名byte别名的目的是当你的程序使用字节作为字符串元素的常见计算度量时而不是与字节数据度量无关的小整数时可以明确这一点。即使byte和uint8在程序编译时是相同的byte通常用于表示数字形式的字符数据而uint8在程序中是一个数字。
rune别名有点不同。其中byte和uint8是完全相同的数据rune可以是一个字节或四个字节一个范围由int32决定。rune用于表示Unicode字符而只有ASCII字符可以只用int32数据类型表示。
此外Go有以下特定于实现的类型:
uint 无符号32或64位
int 有符号32或64位
uintptr 大到足以存储指针值的未解释位的无符号整数特定于实现的类型的大小由编译程序的体系结构定义。
选择数值数据类型
选择正确的大小通常与您正在编程的目标架构的性能有关而不是与您正在使用的数据的大小有关。不过在不需要知道程序性能的具体影响的情况下你可以在刚开始时遵循这些基本指导方针。
如本文前面所讨论的有体系结构无关的类型和特定于实现的类型。对于整数数据通常在Go中使用int或uint等实现类型而不是int64或uint64。这通常会为您的目标架构带来最快的处理速度。例如如果你使用int64并编译为32位架构那么处理这些值需要至少两倍的时间因为在架构中移动数据需要额外的CPU周期。如果你使用int程序会将其定义为32位体系结构的32位大小处理速度会明显更快。
如果您知道不会超过特定的大小范围那么选择一种体系结构无关的类型可以提高速度并减少内存使用。例如如果你知道你的数据不会超过100的值并且只会是一个正数那么选择uint8将使你的程序更高效因为它将需要更少的内存。
我们已经了解了数值数据类型的一些可能的范围下面来看看在程序中超出这些范围会发生什么。
溢出vs.环绕
当您尝试存储大于设计数据类型的值时Go有可能溢出数字和包装数字这取决于该值是在编译时还是在运行时计算的。当程序在尝试构建程序时发现错误时就会发生编译时错误。运行时错误发生在程序被编译之后但它实际上正在执行。
在下面的例子中我们将maxint32设置为最大值:
package mainimport fmtfunc main() {var maxUint32 uint32 4294967295 // Max uint32 sizefmt.Println(maxUint32)
}它将编译并运行结果如下:
Output4294967295如果我们在运行时给值加上1它会被转换成0:
Output0另一方面让我们修改程序在编译前给变量赋值时加上1:
package mainimport fmtfunc main() {var maxUint32 uint32 4294967295 1fmt.Println(maxUint32)}在编译时如果编译器可以确定指定的数据类型容纳的值太大它将抛出overflow错误。这意味着计算的值对于指定的数据类型来说太大。
因为编译器可以确定它会溢出这个值所以它会抛出一个错误:
Outputprog.go:6:36: constant 4294967296 overflows uint32理解数据的边界将帮助你在将来的程序中避免潜在的错误。
我们已经介绍了数值类型下面来看看如何存储布尔值。
布尔值
boolean数据类型可以是两个值之一true或false当声明它为数据类型时它被定义为bool。布尔值用于表示与数学逻辑分支相关的真值它指示计算机科学中的算法。
值true和false将始终分别是小写的t和f因为它们是Go中预先声明的标识符。
许多数学运算的结果要么为true要么为false:
大于 500 100 true1 5 false 小于 200 400 true4 2 false 等于 5 5 true500 400 false
和数字一样我们也可以将布尔值存储在变量中:
myBool : 5 8然后我们可以调用fmt.Println()函数来打印布尔值:
fmt.Println(myBool)由于5不大于8我们将收到以下输出:
Outputfalse随着你在Go中编写更多的程序你将更加熟悉布尔值的工作原理以及计算为true或false的不同函数和操作如何改变程序的进程。
字符串
字符串是由一个或多个字符(字母、数字、符号)组成的序列可以是常量也可以是变量。在Go中字符串存在于反引号或双引号中并根据您使用的引号具有不同的特征。
如果你使用反引号你就是在创建一个原始字符串字面量。如果你使用双引号你是在创建一个解释字符串字面量。
原始字符串字面量
原始字符串字面量是位于反引号之间的字符序列通常称为反引号。在引号内任何字符都将与反引号之间显示的字符一样除了反引号字符本身。
a : Say hello to Go!
fmt.Println(a)OutputSay hello to Go!通常反斜杠用于表示字符串中的特殊字符。例如在解释字符串中\n表示字符串中的新行。然而反斜杠在原始字符串字面量中没有特殊含义:
a : Say hello to Go!\n
fmt.Println(a)因为反斜杠在字符串字面量中没有特殊的含义它实际上会打印出\n的值而不是新建一行:
OutputSay hello to Go!\n原始字符串字面量也可以用来创建多行字符串:
a : This string is on
multiple lines
within a single back
quote on either side.
fmt.Println(a)OutputThis string is on
multiple lines
within a single back
quote on either side.在前面的代码块中新行从输入转移到输出。
解释的字符串字面量
解释字符串字面量是双引号之间的字符序列如bar。在引号中除了换行符和未转义的双引号外任何字符都可以出现。要在解释过的字符串中显示双引号可以使用反斜杠作为转义字符如下所示:
a : Say \hello\ to Go!
fmt.Println(a)OutputSay hello to Go!几乎总是使用解释过的字符串字面量因为它们允许转义字符。
包含UTF-8字符的字符串
UTF-8是一种编码方案用于将可变宽度字符编码为1到4个字节。Go支持开箱即用的UTF-8字符不需要任何特殊设置、库或包。罗马字符(如字母 A )可以用ASCII值(如数字65)表示。但是对于特殊字符如国际字符世则需要使用UTF-8。Go对UTF-8数据使用rune别名类型。
a : Hello, 世界你可以在for循环中使用range关键字来索引Go中的任何字符串即使是UTF-8字符串。for循环和range将在本系列的后面部分更深入地介绍;现在重要的是要知道我们可以使用它来对给定字符串中的字节数进行计数:
package mainimport fmtfunc main() {a : Hello, 世界for i, c : range a {fmt.Printf(%d: %s\n, i, string(c))}fmt.Println(length of Hello, 世界: , len(a))
}在上面的代码块中我们声明了变量a并将值Hello世界赋给它。赋值的文本包含UTF-8字符。
然后我们使用标准的for循环和range关键字。在Go中range关键字将索引一个每次返回一个字符的字符串以及该字符在字符串中的字节索引。
使用fmt.Printf函数我们提供了一个%d: %s\n的格式字符串。’ %d 是数字(在本例中是整数)的打印动词而%s是字符串的打印动词。然后我们提供了i的值i是for循环的当前索引c是for循环的当前字符。
最后我们使用内置的len函数打印出变量a的整个长度。
前面我们提到过rune是int32的别名由1到4个字节组成。世字符需要三个字节来定义在UTF-8字符串范围内索引相应地移动。这就是i在打印出来时不是顺序的原因。
Output0: H
1: e
2: l
3: l
4: o
5: ,
6:
7: 世
10: 界
length of Hello, 世界: 13如你所见这个长度比在字符串上进行范围搜索的次数要长。
你不会总是使用UTF-8字符串但当你使用时你现在会明白为什么它们是runes而不是单个的int32。
声明变量的数据类型
现在您已经了解了不同的基本数据类型我们将介绍如何在go中将这些类型分配给变量。
在Go中我们可以使用关键字var定义一个变量后跟变量名和所需的数据类型。
在下面的例子中我们将声明一个类型为float64的名为pi的变量。
关键字var是第一个声明的东西:
var pi float64然后是我们的变量名pi:
var pi float64最后是数据类型float64:
var pi float64我们也可以指定一个可选的初始值例如3.14:
var pi float64 3.14Go是一门静态类型的语言。静态类型意味着程序中的每条语句都会在编译时被检查。这也意味着数据类型绑定到变量而在动态链接的语言中数据类型绑定到值。
例如在Go中在声明变量时声明类型:
var pi float64 3.14
var week int 7如果声明方式不同每个变量都可能是不同的数据类型。
这与PHP等语言不同PHP的数据类型与值相关:
$s sammy; // $s 自动为字符串类型
$s 123; // $s 自动为数字类型在上面的代码块中第一个$s是一个字符串因为它被赋值为sammy第二个$s是一个整数因为它的值为123。
接下来让我们看看更复杂的数据类型如数组。
数组
An array of strings looks like this: 数组是一组有序的元素序列。数组的容量在创建时定义。一旦数组分配了大小就不能再改变它的大小。因为数组的大小是静态的这意味着它只分配一次内存。这使得数组的使用有些死板但提高了程序的性能。因此优化程序时通常会用到数组。接下来介绍的切片更灵活在其他语言中构成了你所认为的数组。
数组通过声明数组的大小然后在花括号{ }中定义数据类型来定义。
字符串数组如下所示:
[3]string{blue coral, staghorn coral, pillar coral}我们可以将数组存储在变量中并将其打印出来:
coral : [3]string{blue coral, staghorn coral, pillar coral}
fmt.Println(coral)Output[blue coral staghorn coral pillar coral如前所述切片类似于数组但要灵活得多。让我们来看看这个可变数据类型。
切片
切片是一个长度可以改变的有序元素序列。切片可以动态地增加它们的大小。当你向切片中添加新项目时如果切片没有足够的内存来存储新项目它将根据需要向系统请求更多的内存。因为切片可以在需要时扩展以添加更多元素所以切片比数组更常用。
切片是通过在左方括号[]和右方括号{}之间声明数据类型来定义的。
整数切片如下所示:
[]int{-3, -2, -1, 0, 1, 2, 3}浮点数的切片如下所示:
[]float64{3.14, 9.23, 111.11, 312.12, 1.05}字符串切片如下所示:
[]string{shark, cuttlefish, squid, mantis shrimp}让我们将字符串切片定义为seaCreatures:
seaCreatures : []string{shark, cuttlefish, squid, mantis shrimp}我们可以通过调用这个变量来打印它们:
fmt.Println(seaCreatures)Output[shark cuttlefish squid mantis shrimp我们可以使用append关键字将元素添加到切片中。下面的命令将字符串’ seahorse 添加到切片中:
seaCreatures append(seaCreatures, seahorse)你可以通过打印它来验证它是否被添加了:
fmt.Println(seaCreatures)Output[shark cuttlefish squid mantis shrimp seahorse如你所见如果你需要管理未知大小的元素切片比数组更通用。
Maps
map是Go内置的哈希或字典类型。map使用键和值作为一对来存储数据。这在编程中很有用可以通过索引(本例中是键)快速查找值。例如你可能想保存一个用户映射按用户ID索引。键是用户ID, user对象是值。map的构造方法是使用关键字map后面是方括号[]中的键数据类型后面是花括号中的值数据类型和键值对。
map[key]value{}map通常用于保存相关的数据例如ID中包含的信息如下所示:
map[string]string{name: Sammy, animal: shark, color: blue, location: ocean}您会注意到除了大括号之外整个映射中还有冒号。冒号左边的单词是键。在Go中键可以是任何可比较的类型。可比类型是基本类型如strings、ints等。基本类型是由语言定义的不是由任何其他类型组合而成的。虽然它们可以是用户定义的类型但保持简单是最佳实践以避免编程错误。上述字典中的键是:name、animal、color和location。
冒号右边的单词是值。值可以由任何数据类型组成。上述字典中的值是:Sammy、shark、blue和ocean。
让我们将map存储在一个变量中并打印出来:
sammy : map[string]string{name: Sammy, animal: shark, color: blue, location: ocean}
fmt.Println(sammy)Outputmap[animal:shark color:blue location:ocean name:Sammy如果我们想要分离萨米的颜色我们可以通过调用sammy [color]来实现。我们把它打印出来:
fmt.Println(sammy[color])Outputblue由于map提供了用于存储数据的键值对因此它们可以成为Go程序中的重要元素。
总结
此时您应该更好地了解Go中可供使用的一些主要数据类型。当您使用Go语言开发编程项目时这些数据类型中的每一种都将变得非常重要。