看《Go入门指南》 ,这里讲得比较基础,针对go 1.0版,以下是一些我自己觉得特别和不容易理解的地方的摘抄!
上次有说到go里不同类型之间操作必须显示转换,int和uint不固定,所以int 不是int32
int
和uint
在 32 位操作系统上,它们均使用 32 位(4 个字节),在 64 位操作系统上,它们均使用 64 位(8 个字节)。package main func main() { var a int var b int32 a = 15 b = a + a // 编译错误 b = b + 5 // 因为 5 是常量,所以可以通过编译 }
格式化说明符(应该不止这些)
在格式化字符串里,%d
用于格式化整数(%x
和 %X
用于格式化 16 进制表示的数字),%g
用于格式化浮点型(%f
输出浮点数,%e
输出科学计数表示法),%0d
用于规定输出定长的整数,其中开头的数字 0 是必须的。
%n.mg
用于表示数字 n 并精确到小数点后 m 位,除了使用 g 之外,还可以使用 e 或者 f,例如:使用格式化字符串 %5.2e
来输出 3.4 的结果为 3.40e+00
。
%b
是用于表示位的格式化标识符。
4.5.2.3 位运算 (备档)
位运算只能用于整数类型的变量,且需当它们拥有等长位模式时。
%b
是用于表示位的格式化标识符。
二元运算符
-
按位与
&
:对应位置上的值经过和运算结果,具体参见和运算符,第 4.5.1 节,并将 T(true)替换为 1,将 F(false)替换为 0
1 & 1 -> 1 1 & 0 -> 0 0 & 1 -> 0 0 & 0 -> 0
-
按位或
|
:对应位置上的值经过或运算结果,具体参见或运算符,第 4.5.1 节,并将 T(true)替换为 1,将 F(false)替换为 0
1 | 1 -> 1 1 | 0 -> 1 0 | 1 -> 1 0 | 0 -> 0
-
按位异或
^
:对应位置上的值根据以下规则组合:
1 ^ 1 -> 0 1 ^ 0 -> 1 0 ^ 1 -> 1 0 ^ 0 -> 0
-
位清除
&^
:将指定位置上的值设置为 0。
一元运算符
-
按位补足
^
:该运算符与异或运算符一同使用,即
m^x
,对于无符号 x 使用“全部位设置为 1”,对于有符号 x 时使用m=-1
。例如:^2 = ^10 = -01 ^ 10 = -11
-
位左移
<<
:- 用法:
bitP << n
。 -
bitP
的位向左移动 n 位,右侧空白部分使用 0 填充;如果 n 等于 2,则结果是 2 的相应倍数,即 2 的 n 次方。例如:1 << 10 // 等于 1 KB 1 << 20 // 等于 1 MB 1 << 30 // 等于 1 GB
- 用法:
-
位右移
>>
:- 用法:
bitP >> n
。 bitP
的位向右移动 n 位,左侧空白部分使用 0 填充;如果 n 等于 2,则结果是当前值除以 2 的 n 次方。
- 用法:
当希望把结果赋值给第一个操作数时,可以简写为 a <<= 2
或者 b ^= a & 0xffffffff
。
位左移常见实现存储单位的用例
使用位左移与 iota 计数配合可优雅地实现存储单位的常量枚举:
type ByteSize float64
const (
_ = iota // 通过赋值给空白标识符来忽略值
KB ByteSize = 1<<(10*iota)
MB
GB
TB
PB
EB
ZB
YB
)
在通讯中使用位左移表示标识的用例
type BitFlag int
const (
Active BitFlag = 1 << iota // 1 << 0 == 1
Send // 1 << 1 == 2
Receive // 1 << 2 == 4
)
flag := Active | Send // == 3
4.5.2.5 算术运算符
对于整数和浮点数,你可以使用一元运算符 ++
(递增)和 --
(递减),但只能用于后缀,同时,带有 ++
和 --
的只能作为语句
在运算时 溢出 不会产生错误
4.5.4 类型别名
当你在使用某个类型时,你可以给它起另一个名字,然后你就可以在你的代码中使用新的名字(用于简化名称或解决名称冲突)。
在 type TZ int
中,TZ 就是 int 类型的新名称(用于表示程序中的时区),然后就可以使用 TZ 来操作 int 类型的数据。
Example 4.11 type.go
package main
import “fmt”
type TZ int
func main() {
var a, b TZ = 3, 4
c := a + b
fmt.Printf(“c has the value: %d”, c) // 输出:c has the value: 7
}
实际上,类型别名得到的新类型并非和原类型完全相同,新类型不会拥有原类型所附带的方法(第 10 章);TZ 可以自定义一个方法用来输出更加人性化的时区信息。
练习 4.5 定义一个 string
的类型别名 Rope
,并声明一个该类型的变量。
4.5.5 字符类型
严格来说,这并不是 Go 语言的一个类型,字符只是整数的特殊用例。byte
类型是 uint8
的别名,对于只占用 1 个字节的传统 ASCII 编码的字符来说,完全没有问题。例如:var ch byte = 'A'
;字符使用单引号括起来。
在 ASCII 码表中,A 的值是 65,而使用 16 进制表示则为 41,所以下面的写法是等效的:
var ch byte = 65 或 var ch byte = ‘\x41’
(\x
总是紧跟着长度为 2 的 16 进制数)
另外一种可能的写法是 \
后面紧跟着长度为 3 的十进制数,例如:\377
。
不过 Go 同样支持 Unicode(UTF-8),因此字符同样称为 Unicode 代码点或者 runes,并在内存中使用 int 来表示。在文档中,一般使用格式 U+hhhh 来表示,其中 h 表示一个 16 进制数。其实 rune
也是 Go 当中的一个类型,并且是 int32
的别名。
在书写 Unicode 字符时,需要在 16 进制数之前加上前缀 \u
或者 \U
。
因为 Unicode 至少占用 2 个字节,所以我们使用 int16
或者 int
类型来表示。如果需要使用到 4 字节,则会加上 \U
前缀;前缀 \u
则总是紧跟着长度为 4 的 16 进制数,前缀 \U
紧跟着长度为 8 的 16 进制数。
Example 4.12 char.go
var ch int = ‘\u0041’
var ch2 int = ‘\u03B2’
var ch3 int = ‘\U00101234’
fmt.Printf(“%d - %d - %d\n”, ch, ch2, ch3) // integer
fmt.Printf(“%c - %c - %c\n”, ch, ch2, ch3) // character
fmt.Printf(“%X - %X - %X\n”, ch, ch2, ch3) // UTF-8 bytes
fmt.Printf(“%U - %U - %U”, ch, ch2, ch3) // UTF-8 code point
输出:
65 - 946 - 1053236
A - β - r
41 - 3B2 - 101234
U+0041 - U+03B2 - U+101234
格式化说明符 %c
用于表示字符;当和字符配合使用时,%v
或 %d
会输出用于表示该字符的整数;%U
输出格式为 U+hhhh 的字符串(另一个示例见第 5.4.4 节)。
包 unicode
包含了一些针对测试字符的非常有用的函数(其中 ch
代表字符):
判断是否为字母: unicode.IsLetter(ch)
判断是否为数字: unicode.IsDigit(ch)
判断是否为空白符号: unicode.IsSpace(ch)
这些函数返回一个布尔值。包 utf8
拥有更多与 rune 相关的函数。
有疑问加站长微信联系(非本文作者)