GO 中的数据类型

Go 的数据类型分四大类:基础类型,聚合类型,引用类型和接口类型。

整数

Go 同时具备有符号整数和无符号整数。有符号整数分四种大小:8位、16位、32位、64位,用 int8、int16、int32、int64 表示,对应的无符号整数是 uint8、uint16、uint32、uint64。
有符号整数以补码表示,保留最高位作为符号位。
在移位运算 x << n 和 x >> n 中,操作数 n 决定位移量,而且 n 必须为无符号型;操作数x 可以是有符号型也可以是无符号型。算术上,左移运算 x<<n 等价于 x 乘以 2^n;而右移运算 x>>n 等价于x 与其相除,向下取整。

  • len 函数

在下面的示例中,循环中使用的 len 函数,它返回有符号整数

medals := []string{"gold", "silver", "bronze"}
	for i := len(medals); i >= 0; i-- {
		fmt.Println(medals[i])
	}

相反,假若len 返回的结果是无符号整数,就会导致严重的错误,因为 i 也会成为 uint 型,根据定义,条件 i >= 0 将恒成立。第3轮迭代后,有 i == 0,语句 i-- 使得i 成为 uint 型的最大值(例如,可能为 2^64 - 1),而非 -1 ,导致 medals[i]试图越界访问元素,超出 slice 范围,引发运行失败而宕机。

  • fmt 函数输出技巧

在使用 fmt 进行输出的时候,通常 Printf 的格式化字符串含有多个 % 谓词,这要求提供相同数目的操作数,而 % 后的副词 [1] 告知 Printf 重复使用第一个操作数。其次,%o、%x 或 %X 之前的副词 # 告知 Printf 输出相应的前缀0、0x、0X。
用 %c 输出文字符号,如果希望输出带有单引号则使用 %q。

	o := 0666
	fmt.Printf("%d %[1]o %#[1]o\n", o)  // 438 666 0666

	x := int64(0xdeadbeef)
	fmt.Printf("%d %[1]x  %#[1]x %#[1]X\n", x)
	// 3735928559 deadbeef 0xdeadbeef  0XDEADBEEF
	

字符串

字符串操作如下:

	s := "hello  world"
	fmt.Println(s[:5])
	fmt.Println(s[7:])
	fmt.Println(s[:])
	//hello
    //world
    //hello  world

字符串具有不可变性,则其意味着两个字符串能安全地公用同一段底层内存,使得复制任何长度的字符串的开销都很低廉。类似地,字符串s 及其子串(如 s[7:])可以安全地共用数据,因此子串生成操作的开销低廉。这两种操作都没有分配新内存。
字符串操作例子:

func comma(s string) string {
	n := len(s)
	if n <= 3 {
		return s
	}
	return comma(s[: n - 3]) + "," + comma(s[n - 3:])
}

在这里插入图片描述
由于字符串不可变,因此按增量方式构建字符串会导致多次内存分配和复制。这种情况使用 bytes.Buffer 类型会更高效。

常量

常量是一种表达式,其可以保证在编译阶段就计算出表达式的值,并不需要等到运行时,从而使编译器得以知晓其值。所有常量本质上都属于基本类型:布尔型、字符串或数字。
常量的声明可以使用常量生成器 iota,它创建一系列相关值,而不是逐个值显式写出。常量声明中, iota 从0开始取值,逐项加1.

const (
	_  = 1 << (10 * iota)
	KiB       // 1024
	MiB       // 1048576
	GiB       // 1073741824
	TiB       // 1099511627776
	PiB       // 1125899906842624
	EiB       // 1152921504606846976
	ZiB       // 1180591620717411303424
	YiB       // 1208925819614629174706176
)

编译器将从属类型待定的常量表示成某些值,这些值比基本类型的数字精度更高,且算术精度高于原生的机器精度,可以认为它们的精度至少达到256位。从属类型待定的常量共有6种,分别是无类型布尔、无类型整数、无类型文字符号、无类型浮点数、无类型复数、无类型字符串。
借助推迟确定从属类型,无类型常量不仅能暂时维持更高的精度,与类型已确定的常量相比,它们还能写进更多表达式而无需转换类型。比如,上例中 ZiB 和 YiB 的值过大,用哪种整型都无法存储,且它们都是合法常量并且可以用在下面的表达式中:

fmt.Println(YiB/ZiB)   // "1024"

根据除法运算中操作数的类型,除法运算的结果可能是整型或浮点型。所以,常量除法表达式中,操作数选择不同的字面写法会影响结果:

	var f float64 = 212
	fmt.Println((f - 32) * 5 /9)   // 100; (f - 32) * 5 的结果是 float64 型
	fmt.Println(5 / 9 * (f - 32))  // 0; 5/9 的结果是无类型整数, 0
	fmt.Println( 5.0 / 9.0 * (f - 32))  // 100; 5.0/9.0 的结果是无类型浮点数

只有常量才可以是无类型的。若将无类型常量声明为变量(如下面的第一条语句所示),或在类型明确的变量赋值的右方出现无类型常量(如下面的其他三条语句所示),则常量会被隐式转换成该变量的类型。

	var f float64 = 3 + 0i     // 无类型复数 -> float64
	f = 2                      // 无类型整数  -> float64
	f = 1e123                  // 无类型浮点数 -> float64
	f = 'a'                    // 无类型  -> float64

Go 存在各类型的不对对称性:无类型整数可以转换为 int,其大小不确定,但无类型浮点数和无类型复数被转换成大小确定的 float64 和 complex128。Go 中,只有大小不确定的int 类型,却不存在大小不确定的 float 类型和 complex 类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值