1.1 基础类型


1.1.1 布尔类型

go语言的布尔类型与其他的语言基本上无差别,可以通过var flag bool来定义一个布尔变量。布尔类型变量可以支持的位运算包括:与、或、非。

bool类型在内存中占用一个字节的空间,也不支持其他类型强制转换为bool类型。

isOn := true   // 直接赋值
isOff := false
isEqual := (1 == 2) // 也可以表达式的结果计算后赋值

1.1.2 整型

整型在所有语言中的差异不明显,理解了一种语言的整型就可以举一反三的理解其他语言。go语言中整型变量的申明为:var a int,其中var是申请变量的标识,a为变量,int为类型。

go语言中int按照长度和有无符号可以分为以下几类:

有符号 长度 无符号 长度
int8 1个字节 uint8 1个字节
int16 2个字节 uint16 2个字节
int32 4个字节 uint32 4个字节
int64 8个字节 uint64 8个字节
int 32位机器:4个字节
64位机器:8个字节
uint 32位机器:4个字节
64位机器:8个字节

除此之外,还有一个特殊类型的整型uintptr专门用于存储变量的内存地址,在后面的章节中进行介绍。

整型的二进制、八进制、十六进制的表示方法和打印如下:

v := 0b0101   // 二进制
fmt.Printf("%b \n", v)  // 0101
v := 0o555    // 八进制
fmt.Printf("%o \n", v)  // 555
v := 0x12F    // 十六进制
fmt.Printf("%x \n", v)  // 12f
fmt.Printf("%X \n", v)  // 12F

整型之间可以进行类型强制转换,但是需要注意类型表示的数值范围,防止出现长类型转换为短类型后出现截断错误。

var a int = 10
var b uint32
b = uint32(a)   // int类型强制转为uint32类型

1.1.3 浮点型

Go使用两种浮点型变量来存储小数,分别为float32和float64,其采用IEEE-754标准。 float32占用4个字节,其中1位表示符号,8位表示指数,23位表示尾数。小数部分能包含7位,精确6位。 float64占用8个字节,其中1位表示符号,11位表示指数,52位表示尾数。小数部分能包含16位,精确15位。

1. 表示方法

我们可以通过var p float64来定义一个浮点型变量,浮点型的赋值可以分为下面两种方式:

p1 := .1415  // 相当于0.1415
p2 := 1.     // 相当于1.0,小数点一定要加上,不然会被推导为整型

那么p2的类型是什么呢?go语言会将p2自动推导为float64类型,而不是float32类型,这一点需要注意。 浮点类型还可以通过科学计数法来表示很大或者很小的数,通过e或者E来指定指数部分,如:

const Planck = 6.62606957e-34 // 普朗克常数

浮点型打印通过使用%f来格式化输出,且可以控制打印结果的小数点位数。

fmt.Printf("%f\n", math.Pi)      // 打印所有小数
fmt.Printf("%.2f\n", math.Pi)    // 保留两位小数

2. 数值比较

因为浮点数在计算机内部存储并不是精确的,比如0.3+0.6的结果并不是0.9,而是趋近于0.9。这个可以去自行研究IEEE-754标准中关于浮点数存储的知识,本文基础部分不进行介绍。

func main() {
    var p1 float64 = 0.3
    var p2 float64 = 0.6
    fmt.Println(p1+p2)
}
// 输出:0.8999999999999999

因为浮点类型有这样一个属性,那么对于两个浮点类型就不能直接使用==来比较大小了,可能会产生错误的结果。一般是由我们自己定义一个精度,如果两个数差值在精度内,则认为两数相等。

func isEqual(p1, p2 float64){
    if p1 - p2 < 0.000001{
        return true
    }
}

最后,优先使用float64类型,其精度更高。

1.1.4 复数类型

在数学上,复数由两个部分组成,一个是实部,一个是虚部。比如1+i表示实部为1,虚部也为1的复数。

在go语言中,使用两个浮点型来表示一个复数,其中complex64由两个float32来分别表示实部和虚部,complex则是由两个float64来表示实部和虚部的。go也是为数不多内置复数的语言。

复数的声明、实部虚部获取方法:

func complex(r, i FloatType) ComplexType    // 生成一个复数
func real(c ComplexType) FloatType          // 获取复数的实部
func imag(c ComplexType) FloatType          // 获取复数的虚部

// exapmle
b := 1.0 + 2.0i            // b是complex128类型的
Println(real(b))           // 输出+1.000000e+000
Println(imag(b))           // 输出+2.000000e+000

c := complex(1.0, 2.0)     // c是complex128类型的
Println(real(c))           // 输出+1.000000e+000
Println(imag(c))           // 输出+2.000000e+000

由于复数由浮点型来表示,因此复数也继承了浮点型的一些特点,如无法精确表示运算结果,最好不用等号比较大小等。此外,math/cmplx库提供了许多复数操作的函数。

1.1.5 字符串类型

字符串类型也是一种基本类型,底层使用一个数组存储字符串的值。声明一个字符串类型的变量使用var str string,字符串的定义和字符元素的获取:

str := "are you ok"           // 字符串的声明和赋值
first := str[0]                // 获取字符串的第一个字符
last := str[len(str)-1]        // 获取字符串的最后一个字符
fmt.Printf("%s, %c, %c", str, first, last)

也支持定义多行字符串,使用`进行修饰,被修饰的内容,转义字符会失效。如:

str := `a
b
c
d
`
fmt.Println(str)
// 打印输出
a
b
c
d

字符串不支持修改,编译会报错。字符串是只读有很多好处,比如并发安全,方便共享内存。

如果想要修改一个定义的字符串,可以先将字符串转换为切片,然后修改切片后再转为字符串,此时的字符串是一个新的字符串。

1. 基本操作

字符串支持直接进行比较,支持的比较运算符包含==,!=,<,<=,>=,>,举例如下:

if str1 > str2{
    return true
}

字符串的拼接可以直接使用'+',比如:s := str1 + str2,也可以使用格式化输出的方式,比如

s := fmt.Sprintf("%s%s", str1, str2)

不同的拼接方式,性能开销是不一样的,在后续章节中将会介绍这一点。

2. 字符串遍历

字符串支持utf-8和unicode两种编码格式,遍历字符串有多种方式,分别如下:

str := "hello, 世界"
fmt.Println(len(str))  // 长度13,其中1个中文占用3个字符

// 1. utf-8方式遍历
for i := range str{
    fmt.Println(str[i])   // str[i]类型是byte
}
// 2. utf-8方式遍历
for i := 0; i < len(str); i++{
    fmt.Println(str[i])
}
// 3. unicode方式遍历
for i, c := range str{
    // i是下标
    // c是rune类型,rune底层其实是uint32类型
    fmt.Println(c)
}

1.1.6 字符

1.1.7 数组

1.1.8 切片

1.1.9 map

results matching ""

    No results matching ""