当前位置: 首页 > news >正文

国内高校网站建设的调查贵阳网站建设方案书

国内高校网站建设的调查,贵阳网站建设方案书,类似优酷网站建设价格,电脑软件下载网站Go 基础之基本数据类型 文章目录 Go 基础之基本数据类型一、整型1.1 平台无关整型1.1.1 基本概念1.1.2 分类有符号整型#xff08;int8~int64#xff09;无符号整型#xff08;uint8~uint64#xff09; 1.2 平台相关整型1.2.1 基本概念1.2.2 注意点1.2.3 获取三个类型在目标…Go 基础之基本数据类型 文章目录 Go 基础之基本数据类型一、整型1.1 平台无关整型1.1.1 基本概念1.1.2 分类有符号整型int8~int64无符号整型uint8~uint64 1.2 平台相关整型1.2.1 基本概念1.2.2 注意点1.2.3 获取三个类型在目标运行平台上的长度 1.3 整型的溢出问题1.3.1 什么是整形溢出 1.4 整型字面值与格式化输出 二、浮点型2.1 IEEE 754 标准2.2 浮点类型2.3 float32 与float64 这两种浮点类型有什么异同点呢?2.4 浮点型字面值与格式化输出2.4.1 直白地用十进制表示的浮点值形式2.4.2 科学计数法形式2.4.3 浮点数的格式化输出 2.5 math 包2.6 数字类型的极值 三、小结四、复数4.1 复数4.2 复数类型4.3 复数字面值4.4 格式化输出 五、布尔值5.1 布尔类型声明5.2 注意5.3 逻辑运算符 六、字符串6.1 两种写法6.1.1 单行字符串6.1.2 多行字符串 6.2 字符串转义符6.3 字符串特性6.3.1 string 类型的数据是不可变的6.3.2 Go 语言里的字符串的内部实现使用UTF-8编码 6.4 字符串的常用操作6.4.1 字符串拼接6.4.2 字符串长度6.4.3 索引取值6.4.4 字符迭代(一)、for 迭代(二)、for range 迭代 6.4.5 字符串比较6.4.6 字符串转换6.4.7 strings 提供的常用API 七、byte和rune类型7.1 字符7.2 byte7.3 rune7.4 简单示例 八、类型转换九、自定义类型9.1 type 关键字9.2 自定义类型 十、数字类型基本运算10.1 数字类型的基本运算符表格10.2 基本运算 十一、思考 一、整型 所谓整型主要用来表示现实世界中整型数量比如年龄分数排名等等 Go 语言整型可以分为平台无关整型和平台相关整型这两种它们的区别主要就在这些整数类型在不同 CPU 架构或操作系统下面它们的长度是否是一致的。 1.1 平台无关整型 1.1.1 基本概念 Go语言提供了几种平台无关的整数类型它们的长度在不同的平台上是一致的。 1.1.2 分类 平台无关的整型也可以分成两类 有符号整型int8~int64 使用最高位最左边的位作为符号位表示正数和负数。有符号整型的取值范围是从负数到正数因此可以表示负数、零和正数。 无符号整型uint8~uint64 不使用符号位因此只能表示非负数零和正数。无符号整型的取值范围是从零到正数最大值。 类型长度取值范围有符号整型int81个字节[-128, 127]int162个字节[-32768, 32767]int324个字节[- 2147483648, 2147483647]int648个字节[ -9223372036854775808, 9223372036854775807]无符号整型uint81个字节[0, 255]uint162个字节[0, 65535]uint324个字节[0, 4294967295]uint648个字节[0, 18446744073709551615] 有符号整型int8int64和无符号整型uint8uint64两者的本质差别在于最高二进制位bit 位是否被解释为符号位这点会影响到无符号整型与有符号整型的取值范围。 以下图中的这个 8 比特一个字节的整型值为例当它被解释为无符号整型 uint8 时和它被解释为有符号整型 int8 时表示的值是不同的 在同样的比特位表示下当最高比特位被解释为符号位时它代表一个有符号整型int8它表示的值为 -127当最高比特位不被解释为符号位时它代表一个无符号整型 (uint8)它表示的值为 129。 即便最高比特位被解释为符号位上面的有符号整型所表示值也应该为 -1 啊怎么会是 -127 呢 这是因为 Go 采用 2 的补码Two’s Complement作为整型的比特位编码方法。因此我们不能简单地将最高比特位看成负号把其余比特位表示的值看成负号后面的数值。Go 的补码是通过原码逐位取反后再加 1 得到的比如我们以 -127 这个值为例它的补码转换过程就是这样的 1.2 平台相关整型 1.2.1 基本概念 Go语言还提供了一些整数类型它们的长度会根据运行平台的改变而改变这些整数类型的长度依赖于具体的CPU架构和操作系统。 类型32位长度64位长度默认的有符号整型int32位(4字节)64位(8字节)默认的无符号整型unit32位(4字节)64位(8字节)无符号整型uintptr“”“大到足以存储任意一个指针的值”“(Go规范描 述)” 1.2.2 注意点 在这里我们要特别注意一点由于这三个类型的长度是平台相关的所以我们在编写有移植性要求的代码时千万不要强依赖这些类型的长度。 1.2.3 获取三个类型在目标运行平台上的长度 如果你不知道这三个类型在目标运行平台上的长度可以通过 unsafe 包提供的 SizeOf 函数来获取 比如在 x86-64 平台上它们的长度均为 8 var a, b int(5), uint(6) var p uintptr 0x12345678 fmt.Println(signed integer as length is, unsafe.Sizeof(a)) // 8 fmt.Println(unsigned integer bs length is, unsafe.Sizeof(b)) // 8 fmt.Println(uintptrs length is, unsafe.Sizeof(p)) // 81.3 整型的溢出问题 1.3.1 什么是整形溢出 整型溢出指的是在整型变量所能表示的数值范围之外的值。整型变量通常有最大值和最小值限制 无论哪种整型都有它的取值范围也就是有它可以表示的值边界。如果这个整型因为参与某个运算导致结果超出了这个整型的值边界我们就说发生了整型溢出的问题。由于整型无法表示它溢出后的那个“结果”所以出现溢出情况后对应的整型变量的值依然会落到它的取值范围内只是结果值与我们的预期不符导致程序逻辑出错。 var s int8 127 s 1 // 预期128实际结果-128var u uint8 1 u - 2 // 预期-1实际结果255你看有符号整型变量 s 初始值为 127在加 1 操作后我们预期得到 128但由于 128 超出了 int8 的取值边界其实际结果变成了 -128。无符号整型变量 u 也是一样的道理它的初值为 1在进行减 2 操作后我们预期得到 -1但由于 -1 超出了 uint8 的取值边界它的实际结果变成了 255。 这个问题最容易发生在循环语句的结束条件判断中因为这也是经常使用整型变量的地方。无论无符号整型还是有符号整型都存在溢出的问题所以我们要十分小心地选择参与循环语句结束判断的整型变量类型以及与之比较的边界值。 1.4 整型字面值与格式化输出 Go 语言在设计开始就继承了 C 语言关于**数值字面值Number Literal**的语法形式。早期 Go 版本支持十进制、八进制、十六进制的数值字面值形式比如 a : 53 // 十进制 b : 0700 // 八进制以0为前缀 c1 : 0xaabbcc // 十六进制以0x为前缀 c2 : 0Xddeeff // 十六进制以0X为前缀Go 1.13 版本中Go 又增加了对二进制字面值的支持和两种八进制字面值的形式比如 d1 : 0b10000001 // 二进制以0b为前缀 d2 : 0B10000001 // 二进制以0B为前缀 e1 : 0o700 // 八进制以0o为前缀 e2 : 0O700 // 八进制以0O为前缀为提升字面值的可读性Go 1.13 版本还支持在字面值中增加数字分隔符“_”分隔符可以用来将数字分组以提高可读性。比如每 3 个数字一组也可以用来分隔前缀与字面值中的第一个数字 a : 5_3_7 // 十进制: 537 b : 0b_1000_0111 // 二进制位表示为10000111 c1 : 0_700 // 八进制: 0700 c2 : 0o_700 // 八进制: 0700 d1 : 0x_5c_6d // 十六进制0x5c6d不过这里你要注意一下Go 1.13 中增加的二进制字面值以及数字分隔符只在 go.mod 中的 go version 指示字段为 Go 1.13 以及以后版本的时候才会生效否则编译器会报错。 反过来我们也可以通过标准库 fmt 包的格式化输出函数将一个整型变量输出为不同进制的形式。比如下面就是将十进制整型值 59格式化输出为二进制、八进制和十六进制的代码 var a int8 59 fmt.Printf(%b\n, a) //输出二进制111011 fmt.Printf(%d\n, a) //输出十进制59 fmt.Printf(%o\n, a) //输出八进制73 fmt.Printf(%O\n, a) //输出八进制(带0o前缀)0o73 fmt.Printf(%x\n, a) //输出十六进制(小写)3b fmt.Printf(%X\n, a) //输出十六进制(大写)3B二、浮点型 2.1 IEEE 754 标准 IEEE 754 是 IEEE 制定的二进制浮点数算术标准它是 20 世纪 80 年代以来最广泛使用的浮点数运算标准被许多 CPU 与浮点运算器采用。现存的大部分主流编程语言包括 Go 语言都提供了符合 IEEE 754 标准的浮点数格式与算术运算。 IEEE 754 标准规定了四种表示浮点数值的方式单精度32 位、双精度64 位、扩展单精度43 比特以上与扩展双精度79 比特以上通常以 80 位实现。后两种其实很少使用我们重点关注前面两个就好了。 2.2 浮点类型 Go语言支持两种浮点型数float32和float64。这两种浮点型数据格式遵循IEEE 754标准。 浮点类型与前面的整型相比Go 提供的浮点类型都是平台无关的。 2.3 float32 与float64 这两种浮点类型有什么异同点呢? 无论是 float32 还是 float64它们的变量的默认值都为 0.0不同的是它们占用的内存空间大小是不一样的可以表示的浮点数的范围与精度也不同。那么浮点数在内存中的二进制表示究竟是怎么样的呢 浮点数在内存中的二进制表示Bit Representation要比整型复杂得多IEEE 754 规范给出了在内存中存储和表示一个浮点数的标准形式见下图 我们看到浮点数在内存中的二进制表示分三个部分符号位、阶码即经过换算的指数以及尾数。这样表示的一个浮点数它的值等于 其中浮点值的符号由符号位决定当符号位为 1 时浮点值为负值当符号位为 0 时浮点值为正值。公式中 offset 被称为阶码偏移值这个我们待会再讲。 **我们首先来看单精度float32与双精度float64浮点数在阶码和尾数上的不同。**这两种浮点数的阶码与尾数所使用的位数是不一样的你可以看下 IEEE 754 标准中单精度和双精度浮点数的各个部分的长度规定 我们看到单精度浮点类型float32为符号位分配了 1 个 bit为阶码分配了 8 个 bit剩下的 23 个 bit 分给了尾数。而双精度浮点类型除了符号位的长度与单精度一样之外其余两个部分的长度都要远大于单精度浮点型阶码可用的 bit 位数量为 11尾数则更是拥有了 52 个 bit 位。 **接着我们再来看前面提到的“阶码偏移值”我想用一个例子直观地让你感受一下。**在这个例子中我们来看看如何将一个十进制形式的浮点值 139.8125转换为 IEEE 754 规定中的那种单精度二进制表示。 步骤一我们要把这个浮点数值的整数部分和小数 部分分别转换为二进制形式后缀 d 表示十进制数后缀 b 表示二进制数 整数部分139d 10001011b小数部分0.8125d 0.1101b十进制小数转换为二进制可采用“乘 2 取整”的竖式计算。 这样原浮点值 139.8125d 进行二进制转换后就变成 10001011.1101b。 **步骤二移动小数点直到整数部分仅有一个 1也就是 10001011.1101b 1.00010111101b。**我们看到为了整数部分仅保留一个 1小数点向左移了 7 位这样指数就为 7尾数为 00010111101b。 步骤三计算阶码。 IEEE754 规定不能将小数点移动得到的指数直接填到阶码部分指数到阶码还需要一个转换过程。对于 float32 的单精度浮点数而言阶码 指数 偏移值。偏移值的计算公式为 2^(e-1)-1其中 e 为阶码部分的 bit 位数这里为 8于是单精度浮点数的阶码偏移值就为 2^(8-1)-1 127。这样在这个例子中阶码 7 127 134d 10000110b。float64 的双精度浮点数的阶码计算也是这样的。 **步骤四将符号位、阶码和尾数填到各自位置得到最终浮点数的二进制表示。**尾数位数不足 23 位可在后面补 0。 这样最终浮点数 139.8125d 的二进制表示就为 0b_0_10000110_00010111101_000000000000。 最后我们再通过 Go 代码输出浮点数 139.8125d 的二进制表示和前面我们手工转换的做一下比对看是否一致。 func main() {var f float32 139.8125bits : math.Float32bits(f)fmt.Printf(%b\n, bits) }在这段代码中我们通过标准库的 math 包将 float32 转换为整型。在这种转换过程中float32 的内存表示是不会被改变的。然后我们再通过前面提过的整型值的格式化输出将它以二进制形式输出出来。运行这个程序我们得到下面的结果 1000011000010111101000000000000我们看到这个值在填上省去的最高位的 0 后与我们手工得到的浮点数的二进制表示一模一样。这就说明我们手工推导的思路并没有错。 而且你可以从这个例子中感受到阶码和尾数的长度决定了浮点类型可以表示的浮点数范围与精度。因为双精度浮点类型float64阶码与尾数使用的比特位数更多它可以表示的精度要远超单精度浮点类型所以在日常开发中我们使用双精度浮点类型float64的情况更多这也是 Go 语言中浮点常量或字面值的默认类型。 而 float32 由于表示范围与精度有限经常会给开发者造成一些困扰。比如我们可能会因为 float32 精度不足导致输出结果与常识不符。比如下面这个例子就是这样f1 与 f2 两个浮点类型变量被两个不同的浮点字面值初始化但逻辑比较的结果却是两个变量的值相等。至于其中原因我将作为思考题留给你你可以结合前面讲解的浮点类型表示方法对这个例子进行分析 var f1 float32 16777216.0 var f2 float32 16777217.0 fmt.Println(f1 f2) // true看到这里你是不是觉得浮点类型很神奇和易用易理解的整型相比浮点类型无论在二进制表示层面还是在使用层面都要复杂得多。 2.4 浮点型字面值与格式化输出 2.4.1 直白地用十进制表示的浮点值形式 这一类我们通过字面值就可直接确定它的浮点值比如 3.1415 .15 // 整数部分如果为0整数部分可以省略不写 81.80 82. // 小数部分如果为0小数点后的0可以省略不写2.4.2 科学计数法形式 采用科学计数法表示的浮点字面值我们需要通过一定的换算才能确定其浮点值。而且在这里科学计数法形式又分为十进制形式表示的和十六进制形式表示的两种。 使用十进制科学计数法形式的浮点数字面值这里字面值中的 e/E 代表的幂运算的底数为 10 6674.28e-2 // 6674.28 * 10^(-2) 66.742800 .12345E5 // 0.12345 * 10^5 12345.000000接着是十六进制科学计数法形式的浮点数 0x2.p10 // 2.0 * 2^10 2048.000000 0x1.Fp0 // 1.9375 * 2^0 1.937500这里我们要注意十六进制科学计数法的整数部分、小数部分用的都是十六进制形式但指数部分依然是十进制形式并且字面值中的 p/P 代表的幂运算的底数为 2。 2.4.3 浮点数的格式化输出 知道了浮点型的字面值后和整型一样fmt 包也提供了针对浮点数的格式化输出。我们最常使用的格式化输出形式是 %f。通过 %f我们可以输出浮点数最直观的原值形式。 var f float64 123.45678 fmt.Printf(%f\n, f) // 123.456780我们也可以将浮点数输出为科学计数法形式如下面代码 fmt.Printf(%e\n, f) // 1.234568e02 fmt.Printf(%x\n, f) // 0x1.edd3be22e5de1p06其中 %e 输出的是十进制的科学计数法形式而 %x 输出的则是十六进制的科学计数法形式。 2.5 math 包 math 包是Go语言标准库中的一个核心包它提供了各种数学函数和常量用于进行各种数学操作。 2.6 数字类型的极值 在Go语言中数字类型的极值常量通常存储在math包中。这些常量用于表示浮点数和整数类型的最大值和最小值以及其他数学常量。 int 和 uint 族都有最大值和最小值。float32 和 float64 只有最大值和最小正数 没有最小值。 以下是一些常见的math包中的数字类型极值常量 整数类型的极值 math.MaxInt8: int8 类型的最大值。math.MinInt8: int8 类型的最小值。math.MaxInt16: int16 类型的最大值。math.MinInt16: int16 类型的最小值。math.MaxInt32: int32 类型的最大值。math.MinInt32: int32 类型的最小值。math.MaxInt64: int64 类型的最大值。math.MinInt64: int64 类型的最小值。 浮点数类型的极值 math.MaxFloat32: float32 类型的最大正有限值。math.SmallestNonzeroFloat32: float32 类型的最小正非零值。math.MaxFloat64: float64 类型的最大正有限值。math.SmallestNonzeroFloat64: float64 类型的最小正非零值。 其他数学常量 math.Pi: 圆周率 π 的近似值。math.E: 自然对数的底数 e 的近似值。math.Sqrt2 和 math.SqrtE平方根的近似值。 这些常量可以在你的Go程序中使用以便在算法和数学计算中引用数字类型的极值和常量。例如你可以使用 math.MaxInt64 来表示 int64 类型的最大值以便进行整数计算时进行比较或限制数值范围。同样math.Pi 可用于计算圆的周长或面积等数学运算。 package mainimport (fmtmath )func main() {// 整数类型的极值fmt.Println(int8 Max:, math.MaxInt8)fmt.Println(int8 Min:, math.MinInt8)fmt.Println(int16 Max:, math.MaxInt16)fmt.Println(int16 Min:, math.MinInt16)fmt.Println(int32 Max:, math.MaxInt32)fmt.Println(int32 Min:, math.MinInt32)fmt.Println(int64 Max:, math.MaxInt64)fmt.Println(int64 Min:, math.MinInt64)// 浮点数类型的极值fmt.Println(float32 Max:, math.MaxFloat32)fmt.Println(float32 Smallest Non-zero:, math.SmallestNonzeroFloat32)fmt.Println(float64 Max:, math.MaxFloat64)fmt.Println(float64 Smallest Non-zero:, math.SmallestNonzeroFloat64)// 其他数学常量fmt.Println(Pi:, math.Pi)fmt.Println(E:, math.E)fmt.Println(Sqrt(2):, math.Sqrt2)fmt.Println(Sqrt(E):, math.SqrtE) } 三、小结 int 家族int8、int16、int32、int64、int。在内存中分别用 1、2、4、8 个字节来表达而 int 用几个字节则取决于CPU。目前大多数 int 都是 8 字节。 如果犹豫不决就优先使用int特殊情况除外。 uint 家族uint8、uint16、uint32、uint64、 uint。无符号整数类似于 int 家族优先使用 uint。 float 家族float32、float64。浮点数优先使用 float64。 四、复数 4.1 复数 数学课本上将形如 zabia、b 均为实数a 称为实部b 称为虚部的数称为复数。 Go 语言则原生支持复数类型。 和整型、浮点型相比复数类型在 Go 中的应用就更为局限和小众主要用于专业领域的计算比如矢量计算等。我们简单了解一下就可以了。 4.2 复数类型 Go 提供两种复数类型它们分别是 complex64 和 complex128。 complex64 的实部与虚部都是 float32 类型而 complex128 的实部与虚部都是 float64 类型。 如果一个复数没有显示赋予类型那么它的默认类型为 complex128。 4.3 复数字面值 关于复数字面值的表示我们其实有三种方法。 第一种我们可以通过复数字面值直接初始化一个复数类型变量 var c 5 6i var d 0o123 .12345E5i // 8312345i第二种Go 还提供了 complex 函数方便我们创建一个 complex128 类型值 var c complex(5, 6) // 5 6i var d complex(0o123, .12345E5) // 8312345i第三种你还可以通过 Go 提供的预定义的函数 real 和 imag来获取一个复数的实部与虚部返回值为一个浮点类型 var c complex(5, 6) // 5 6i r : real(c) // 5.000000 i : imag(c) // 6.0000004.4 格式化输出 复数形式的格式化输出的问题由于 complex 类型的实部与虚部都是浮点类型所以我们可以直接运用浮点型的格式化输出方法来输出复数类型以下是一个示例 package mainimport fmtfunc main() {// 创建复数z : complex(3, 4) // 3 4i// 获取复数的实部和虚部并使用浮点型格式化输出realPart : real(z)imagPart : imag(z)fmt.Printf(Real Part: %f\n, realPart)fmt.Printf(Imaginary Part: %f\n, imagPart) } 五、布尔值 5.1 布尔类型声明 在Go语言中可以使用bool关键字来声明布尔类型变量这些变量只能取 true真或 false假这两个值。 var isTrue bool true var isFalse bool false5.2 注意 默认值布尔类型变量的默认值为false。 var a boolfmt.Println(a) // 输出为false强制类型转换Go语言不允许将整数或其他数据类型强制转换为布尔型。只有布尔类型的值可以被用于布尔表达式中比如条件语句。 var x string 2222// 错误cannot convert x (variable of type string) to type boolvar isTrue bool bool(x)fmt.Println(isTrue)数值运算和转换布尔型无法直接参与数值运算也无法与其他数据类型进行数值转换。这是因为布尔类型只有两个可能的值不适合数学运算或数值转换。 var b bool true var i int 10// 错误无法将布尔型和整数相加 // var result b i// 错误无法将整数转换为布尔型 // var b2 bool bool(i)5.3 逻辑运算符 运算符说明示例结果! (非)取反,将真变假,假变真!truefalse (与)两边都为真,结果为真,否则为假true falsefalse|| (或)两边任意一边为真,结果为真,两边都为假,结果为假true || falsetrue (等于)两边相等,结果为真;不相等,结果为假1 1true! (不等于)两边不相等,结果为真;相等,结果为假1 ! 2true package mainimport fmtfunc main() {var isTrue bool truevar isFalse bool false// 布尔值的逻辑运算andResult : isTrue isFalse // 与运算结果为 falseorResult : isTrue || isFalse // 或运算结果为 truenotResult : !isTrue // 非运算结果为 falsefmt.Println(AND result:, andResult)fmt.Println(OR result:, orResult)fmt.Println(NOT result:, notResult) }六、字符串 6.1 两种写法 6.1.1 单行字符串 使用双引号 来定义: s1 : This is a string6.1.2 多行字符串 使用反引号 来定义: var s string ,_---~~~~~----.__,,_,*^____ _____*g*\*,--,/ __/ / ^. / \ ^q f[ f | )) | | )) l 0 _/\/ \~____ / __ \_____/ \| _l__l_ I} [______] I] | | | |] ~ ~ || || | fmt.Println(s)多行字符串中可以直接加入换行,并且会原样保留换行符。 多行字符串常用于需要编写包含换行的长文本。 需要注意: 单双引号定义的字符串效果一样多行字符串会保留文字中的空格和换行不能在单行字符串内直接换行,需要使用转义符\n 6.2 字符串转义符 Go 语言的字符串常见转义符包含回车、换行、单双引号、制表符等如下表所示。 转义符含义\r回车符返回行首\n换行符直接跳到下一行的同列位置\t制表符\单引号\双引号\\反斜杠 举个例子我们要打印一个Windows平台下的一个文件路径 package main import (fmt ) func main() {fmt.Println(str : \c:\\Code\\lesson1\\go.exe\) }6.3 字符串特性 6.3.1 string 类型的数据是不可变的 string 类型的数据是不可变的提高了字符串的并发安全性和存储利用率。 Go 语言规定字符串类型的值在它的生命周期内是不可改变的。这就是说如果我们声明了一个字符串类型的变量那我们是无法通过这个变量改变它对应的字符串值的但这并不是说我们不能为一个字符串类型变量进行二次赋值。 什么意思呢我们看看下面的代码就好理解了 var s string hello s[0] k // 错误字符串的内容是不可改变的 s gopher // ok在这段代码中我们声明了一个字符串类型变量 s。当我们试图通过下标方式把这个字符串的第一个字符由 h 改为 k 的时候我们会收到编译器错误的提示字符串是不可变的。但我们仍可以像最后一行代码那样为变量 s 重新赋值为另外一个字符串。 Go 这样的“字符串类型数据不可变”的性质给开发人员带来的最大好处就是我们不用再担心字符串的并发安全问题。这样Go 字符串可以被多个 GoroutineGo 语言的轻量级用户线程共享开发者不用因为担心并发安全问题使用会带来一定开销的同步机制。 另外也由于字符串的不可变性针对同一个字符串值无论它在程序的几个位置被使用Go 编译器只需要为它分配一块存储就好了大大提高了存储利用率。 6.3.2 Go 语言里的字符串的内部实现使用UTF-8编码 对非 ASCII 字符提供原生支持消除了源码在不同环境下显示乱码的可能。 Go 语言源文件默认采用的是 Unicode 字符集Unicode 字符集是目前市面上最流行的字符集它囊括了几乎所有主流非 ASCII 字符包括中文字符。Go 字符串中的每个字符都是一个 Unicode 字符并且这些 Unicode 字符是以 UTF-8 编码格式存储在内存当中的。 6.4 字符串的常用操作 6.4.1 字符串拼接 使用操作符拼接字符串 s : hello world println(s)通过fmt.Sprintf进行格式化拼接 println(fmt.Sprintf(hello %d, 123))6.4.2 字符串长度 使用len() 获取字符串字节长度: println(len(你好)) // 输出6println(len(你好abc)) // 输出9使用utf8.RuneCountInString()函数获取字符个数: println(utf8.RuneCountInString(你好abc)) // 输出56.4.3 索引取值 在字符串的实现中真正存储数据的是底层的数组。字符串的下标操作本质上等价于底层数组的下标操作。可以通过索引下标访问字符串中每个字符: var s 中国人 fmt.Printf(0x%x\n, s[0]) // 0xe4字符“中” utf-8编码的第一个字节我们可以看到通过下标操作我们获取的是字符串中特定下标上的字节而不是字符。 6.4.4 字符迭代 Go 有两种迭代形式常规 for 迭代与 for range 迭代。你要注意通过这两种形式的迭代对字符串进行操作得到的结果是不同的。 (一)、for 迭代 通过常规 for 迭代对字符串进行的操作是一种字节视角的迭代每轮迭代得到的的结果都是组成字符串内容的一个字节以及该字节所在的下标值这也等价于对字符串底层数组的迭代比如下面代码 var s 中国人for i : 0; i len(s); i {fmt.Printf(index: %d, value: 0x%x\n, i, s[i]) }运行这段代码我们会看到经过常规 for 迭代后我们获取到的是字符串里字符的 UTF-8 编码中的一个字节 index: 0, value: 0xe4 index: 1, value: 0xb8 index: 2, value: 0xad index: 3, value: 0xe5 index: 4, value: 0x9b index: 5, value: 0xbd index: 6, value: 0xe4 index: 7, value: 0xba index: 8, value: 0xba(二)、for range 迭代 像下面这样使用 for range 迭代我们得到的又是什么呢我们继续看代码 var s 中国人for i, v : range s {fmt.Printf(index: %d, value: 0x%x\n, i, v) }同样运行一下这段代码我们得到 index: 0, value: 0x4e2d index: 3, value: 0x56fd index: 6, value: 0x4eba我们看到通过 for range 迭代我们每轮迭代得到的是字符串中 Unicode 字符的码点值以及该字符在字符串中的偏移值。我们可以通过这样的迭代获取字符串中的字符个数而通过 Go 提供的内置函数 len我们只能获取字符串内容的长度字节个数。当然了获取字符串中字符个数更专业的方法是调用标准库 UTF-8 包中的 RuneCountInString 函数。 6.4.5 字符串比较 Go 字符串类型支持各种比较关系操作符包括 、! 、、、 和 。在字符串的比较上Go 采用字典序的比较策略分别从每个字符串的起始处开始逐个字节地对两个字符串类型变量进行比较。 当两个字符串之间出现了第一个不相同的元素比较就结束了这两个元素的比较结果就会做为串最终的比较结果。如果出现两个字符串长度不同的情况长度比较小的字符串会用空元素补齐空元素比其他非空元素都小。 以下是Go 字符串比较的示例 func main() {// s1 : 世界和平s2 : 世界 和平fmt.Println(s1 s2) // true// !s1 Gos2 Cfmt.Println(s1 ! s2) // true// and s1 12345s2 23456fmt.Println(s1 s2) // truefmt.Println(s1 s2) // true// and s1 12345s2 123fmt.Println(s1 s2) // truefmt.Println(s1 s2) // true }你可以看到鉴于 Go string 类型是不可变的所以说如果两个字符串的长度不相同那么我们不需要比较具体字符串数据也可以断定两个字符串是不同的。但是如果两个字符串长度相同就要进一步判断数据指针是否指向同一块底层存储数据。如果还相同那么我们可以说两个字符串是等价的如果不同那就还需要进一步去比对实际的数据内容。 6.4.6 字符串转换 在这方面Go 支持字符串与字节切片、字符串与 rune 切片的双向转换并且这种转换无需调用任何函数只需使用显式类型转换就可以了。我们看看下面代码 var s string 中国人// string - []rune rs : []rune(s) fmt.Printf(%x\n, rs) // [4e2d 56fd 4eba]// string - []byte bs : []byte(s) fmt.Printf(%x\n, bs) // e4b8ade59bbde4baba// []rune - string s1 : string(rs) fmt.Println(s1) // 中国人// []byte - string s2 : string(bs) fmt.Println(s2) // 中国人6.4.7 strings 提供的常用API strings包提供了Go语言字符串操作的常用API: 函数说明strings.Contains(s, substr)判断字符串s是否包含子串substrstrings.Index(s, substr)返回子串substr在s中首次出现的索引strings.Join(a[]string, sep)将字符串数组a通过sep连接起来strings.Repeat(s, count)重复s字符串count次strings.Replace(s, old, new, n)将s中的old子串替换为new,最多n次strings.Split(s, sep)通过sep分割s字符串,返回子串数组strings.ToLower(s)s全部转为小写strings.ToUpper(s)s全部转为大写strings.Fields(s)将字符串s按空格分解为子串数组strings.TrimSpace(s)去除s头尾空白字符 七、byte和rune类型 7.1 字符 组成每个字符串的元素叫做“字符”可以通过遍历或者单个获取字符串元素获得字符。 字符用单引号’包裹起来如 var a 中 var b x7.2 byte byte类型代表了ASCII码的一个字符。字节的值范围是0到255。是 uint8 的别名。byte类型经常用于处理二进制数据流,或需要处理ASCII字符时,如读写文件,数据流的编码解码等。 例如: var a byte A7.3 rune rune 是 int32 的别名它用于表示32位的Unicode字符范围从0到65535,。rune类型代表一个UTF-8字符。实际上它是一个int32的别名。rune 类型通常用于处理文本和字符串特别是当需要支持多语言字符集如UTF-8编码的Unicode字符时。比如需要处理中文、日文或者其他复合字符时则需要用到rune类型。 例如 var a rune 国7.4 简单示例 以下是一些示例演示了byte 和 rune 类型的用法 package mainimport fmtfunc main() {// 使用 byte 表示单个 ASCII 字符var ch byte Afmt.Printf(byte: %c\n, ch)// 使用 rune 表示 Unicode 字符var ru rune 你fmt.Printf(rune: %c\n, ru)// 使用 rune 处理字符串中的 Unicode 字符str : 你好世界for _, char : range str {fmt.Printf(rune: %c\n, char)} }在上述示例中我们首先使用 byte 和 rune 分别表示单个ASCII字符和Unicode字符。然后我们使用 rune 处理包含多个Unicode字符的字符串。 总之byte 和 rune 类型在Go语言中用于处理字符和字节其中 byte 主要用于处理ASCII字符和字节数据而 rune 用于处理Unicode字符特别是用于处理多语言文本。 八、类型转换 Go语言中只有强制类型转换没有隐式类型转换。该语法只能在两个类型之间支持相互转换的时候使用。 强制类型转换的基本语法如下 T(expression)其中T 表示要转换的目标类型expression 是要转换的表达式。这个语法只能在两种数据类型之间支持相互转换的情况下使用。 以下是一些示例演示了不同数据类型之间的强制类型转换 package mainimport fmtfunc main() {// 整数到浮点数的转换var x int 42y : float64(x)fmt.Printf(x: %d, y: %f\n, x, y)// 浮点数到整数的转换截断小数部分var a float64 3.14b : int(a)fmt.Printf(a: %f, b: %d\n, a, b)// 类型不匹配需要显式转换var c int 10var d int64 int64(c)fmt.Printf(c: %d, d: %d\n, c, d)// 字符串到字节切片的转换str : Hello, Go!bytes : []byte(str)fmt.Printf(str: %s, bytes: %v\n, str, bytes) } 要注意的是,强制类型转换必须在相互兼容的类型之间进行,且需要明确指定目标类型,不会自动进行隐式转换。 九、自定义类型 9.1 type 关键字 如果我们要通过 Go 提供的类型定义语法来创建自定义的数值类型我们可以通过 type 关键字基于原生内置类型来声明一个新类型。 9.2 自定义类型 下面我们就来建立一个名为 MyInt 的新的数值类型看看 type MyInt int32这里因为 MyInt 类型的底层类型是 int32所以它的数值性质与 int32 完全相同但它们仍然是完全不同的两种类型。根据 Go 的类型安全规则我们无法直接让它们相互赋值或者是把它们放在同一个运算中直接计算这样编译器就会报错。 var m int 5 var n int32 6 var a MyInt m // 错误在赋值中不能将mint类型作为MyInt类型使用 var a MyInt n // 错误在赋值中不能将nint32类型作为MyInt类型使用要避免这个错误我们需要借助显式转型让赋值操作符左右两边的操作数保持类型一致像下面代码中这样做 var m int 5 var n int32 6 var a MyInt MyInt(m) // ok var a MyInt MyInt(n) // ok我们也可以通过 Go 提供的类型别名Type Alias语法来自定义数值类型。和上面使用标准 type 语法的定义不同的是通过类型别名语法定义的新类型与原类型别无二致可以完全相互替代。我们来看下面代码 type MyInt int32var n int32 6 var a MyInt n // ok你可以看到通过类型别名定义的 MyInt 与 int32 完全等价所以这个时候两种类型就是同一种类型不再需要显式转型就可以相互赋值。 十、数字类型基本运算 10.1 数字类型的基本运算符表格 运算符描述示例加法x y-减法x - y*乘法x * y/除法x / y%求余x % y自增x–自减x– 10.2 基本运算 在Go语言中数字类型包括整数和浮点数支持基本的数学运算包括加法、减法、乘法和除法。以下是这些运算的示例 package mainimport fmtfunc main() {// 整数运算var a, b int 10, 5// 加法sum : a bfmt.Printf(a b %d\n, sum)// 减法difference : a - bfmt.Printf(a - b %d\n, difference)// 乘法product : a * bfmt.Printf(a * b %d\n, product)// 除法quotient : a / bfmt.Printf(a / b %d\n, quotient)// 浮点数运算var x, y float64 3.14, 1.5// 加法sumFloat : x yfmt.Printf(x y %f\n, sumFloat)// 减法differenceFloat : x - yfmt.Printf(x - y %f\n, differenceFloat)// 乘法productFloat : x * yfmt.Printf(x * y %f\n, productFloat)// 除法quotientFloat : x / yfmt.Printf(x / y %f\n, quotientFloat) } 十一、思考 下面例子中 f1 为何会与 f2 相等 package mainimport fmtfunc main() {var f1 float32 16777216.0var f2 float32 16777217.0fmt.Println(f1 f2) // true }欢迎在留言区留下你的答案。
http://www.w-s-a.com/news/839599/

相关文章:

  • 做国外单的网站叫什么海南省海口市网站建设
  • 杭州响应式网站案例wordpress5.2.2
  • 网站建设运营维护合同wordpress资源搜索插件
  • 国外网站流量查询东莞网站建设教程
  • 餐饮类网站建设达到的作用东莞工程建设交易中心网
  • 网站设计 知识产权湖北网站建设xiduyun
  • 猫咪网站模版下载中国风 古典 红色 网站源代码
  • 个人网站备案模板制作网站首页
  • 潍坊正规建设网站网站建设设计作业
  • 推荐一下网站谢谢辽宁住房城乡建设部官方网站
  • 网站文件大小英选 网站开发
  • 济南建网站哪家好wordpress编辑器排行
  • 在福州做搬家网站多少钱画册设计网站有哪些
  • 如何让别人浏览我做的网站哪些方法可以建设网站
  • 网站建设与管理网络推广的优点
  • 美食网站的设计与制作做网站的电销话术
  • 中国档案网站建设现状研究陕西建设厅执业资格注册中心网站
  • 网站建设的内容管理怎么用ps切片在dw里做网站
  • 建设婚恋网站用什么搭建涿州网站开发
  • 做知识内容的网站与app哈尔滨哪里有做网站的
  • 青岛企业网站建站模板百度网站建设推广
  • 做360网站中保存的图片存在哪里个人建立网站要多少钱
  • 网站安装部署无锡做网站的公司
  • 怎么将网站做成小程序安装wordpress到服务器
  • 企业网站建设的四大因素沈阳网站建设招标公司
  • wordpress仿站开发公司网站策划宣传
  • 金乡县网站开发网站开发三个流程
  • qq空间网站是多少纺织网站建设方案
  • 建设微网站项目报告网站优化难吗
  • 做网站需要自己上传产品吗企业网站系统设计