3 基本数据类型

基本数据类型包括:整型、浮点型、布尔型、字符串。

除以上基本类型之外,还有 数组、切片、结构体、函数、map、通道 等。

3.1 整型

3.1.1 整型

整型分为:int8int16int32int64 ,以及对应的无符号整型:uint8uint16uint32uint64

其中 unit8 对应其他语言中的 byte 类型;int16 对应 C 语言中的 short 类型;int64 对应 C 语言中的 long 类型。

各数据类型及对应的取值关系如下:

![](/note_image/Go/0 Go基础语法/pics/3-1-整型及对应的数据类型.png)

特殊整型:

![](/note_image/Go/0 Go基础语法/pics/3-2-特殊整型.png)

注意: 获取对象的长度时,内建的 len() 函数返回的长度可以根据不同平台的字节长度进行变化。实际使用中,切片或 map 的元素数量等都可以直接使用 int 来表示 。

3.1.2 八进制和十六进制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package main

import (
"fmt"
)

func main() {
// 声明十进制数.
var a = 10
// %d 为十进制数的占位符,表示输出十进制数——10
fmt.Printf("%d \n", a)
// %b 为二进制数的占位符,输出二进制数——1010
fmt.Printf("%b \n", a)
// %o 为八进制数的占位符,输出八进制数——12
fmt.Printf("%o \n", a)
// %x 为十六进制数的占位符,输出十六进制数——a
fmt.Printf("%x \n", a)
// %T 表示获取某个变量的类型_int
fmt.Printf("%T \n", a)

// 声明八进制数,以 0 开头
b := 077
// 63
fmt.Printf("%d \n", b)
//111111
fmt.Printf("%b \n", b)
// 77
fmt.Printf("%o \n", b)
// 3f
fmt.Printf("%x \n", b)
// int
fmt.Printf("%T \n", b)

// 声明 16 进制数,以 0x开头
c := 0xff
// 255
fmt.Printf("%d \n", c)
// 11111111
fmt.Printf("%b \n", c)
// 377
fmt.Printf("%o \n", c)
// ff
fmt.Printf("%x \n", c)
// int
fmt.Printf("%T \n", c)

// 显示声明为 int8 类型,否则,默认 int 类型
d := int8(9)
// 9
fmt.Printf("%d \n", d)
// 1001
fmt.Printf("%b \n", d)
// 11
fmt.Printf("%o \n", d)
// 9
fmt.Printf("%x \n", d)
// int8
fmt.Printf("%T \n", d)

// %v 表示获取某个变量的值——int8,9
fmt.Printf("d 的类型为:%T,值为: %v", d, d)
}

3.2 浮点型

go 语言支持两种浮点型数,float32float64.

这两种浮点型数据格式遵循 IEEE 754 标准, float32 的浮点数的最大范围约为 3.4e38 ,可以使用常量定义:math.MaxFloat32。float64 的浮点数的最大范围约为 1.8e308, 可以使用常量定义 math.MaxFloat64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
"math"
)

func main() {
// %f 为浮点数的占位符,
fmt.Printf("%f \n", math.MaxFloat32)
fmt.Printf("%f \n", math.MaxFloat64)

var a = 1.2345
// 默认 floa64
fmt.Printf("%T \n", a)

var b = float32(1.2345)
// 显示声明为 float32
fmt.Printf("%T \n", b)
}

3.3 复数

  • 复数实际上是有两个实数(浮点数)的组合,一个表示实部(real),一个表示虚部(imag)。
  • 虚部需要添加 i 作为后缀。
  • real(复数)可以获取实部 ,imag(复数) 可以获取虚部
  • complex64complex128 两种类型,complex64 的实部和虚部为 32 位,complex128 的实部和虚部为 64 位。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

func main() {
// 1、声明一个复数
var v1 complex64
// 虚部数据需要后缀 i
v1 = 3.2 + 12i
fmt.Println("v1=", v1)

// 2、自动推导类型的复数
v2 := 3.3 + 2.0i
fmt.Printf("v2的类型为:%T \n", v2)
fmt.Println("v2的值为:", v2)

// 3、获取复数的实部和虚部: real(复数),imag(复数)
fmt.Println("v2的实部为:", real(v2), "v2的虚部为:", imag(v2))
}

运行结果:

1
2
3
4
5
cnpeng$ go run Day1.go 
v1= (3.2+12i)
v2的类型为:complex128
v2的值为: (3.3+2i)
v2的实部为: 3.3 v2的虚部为: 2

3.4 布尔类型

3.4.1 布尔类型

go 语言中以 bool 声明布尔类型数据。布尔类型仅有 truefalse 两种值。

注意:

  • 布尔类型变量的默认值为 false
  • go 语言中不允许将整型强制转换为布尔类型
  • 布尔型数据无法参与数值运算,与无法与其他类型进行转换。

3.4.2 补充:格式化输出的总结

fmt 包的 Printf() 格式化输出可以使用下面的格式化符号:

格式 含义
%% % 字面量
%b 二进制整数值(基数为2),或者是(高级的)用科学计数法表示的指数为2的浮点数
%c 字符型。可以把输入的数字按照 ASCII 码转换为对应的字符。
%d 十进制数值(基数为10)
%e 以科学计数法 e 表示的浮点数或者复数值
%E 以科学计数法 E 表示的浮点数或者复数值
%f 以标准计数法表示的浮点数或者复数值
%g %e或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出
%G %E或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出
%o 以八进制表示的数字
%p 以十六进制表示的值的地址,前缀为 0x, 字母使用小小的 a-f 表示
%s 字符串
%t 以 true 或者 false 输出布尔值
%T 获取数据类型。
%U 用 Unicode 表示法表示的整型码点。默认值为四个数字字符
%v 使用默认格式输出的内置或自定义类型的值。或者时使用期望类型的 String() 方式输出的自定义值。
%#v 如果输出的字符串,该字符串会被双引号包裹起来
%x 以十六进制表示的整型值, a-f 使用小写
%X 以十六进制表示的整型值, A-F 使用大写
1
2
3
4
5
6
7
8
9
10
11
package main

import (
"fmt"
)

func main() {
var str = "abc"
// "abc"
fmt.Printf("%#v \n", str)
}

3.4 字符串

go 语言中的字符串以原生数据类型出现,使用字符串就想使用其他原生数据类型(int、bool、float32、float64 等)一样。

go 语言中字符串的内部实现使用了 UTF-8 编码。字符串的值使用双引号 " " 包裹( go 语言中,只有使用单引号 ' ' 包裹的是字符)。

3.4.1 字符串转义符

转义符 含义
\r 回车符(返回行首)
\n 换行符
\t 制表符
\' 单引号
\" 双引号
\\ 反斜杠

1字节=8Bit ,即1字节表示八个二进制位,也就是 八个 01——01010101
一个 UTF-8 编码的汉字通常占用三个字节,偏僻字可能会占四个字节。

1
2
3
4
5
6
7
8
9
10
11
package main

import (
"fmt"
)

func main() {
// 打印 windows 下的一个文件目录,需要使用转义字符
// 输出结果:"D:\Go\src\code.github.cnoeng\stu"
fmt.Printf("\"D:\\Go\\src\\code.github.cnoeng\\stu\"")
}

3.4.2 多行字符串(原样字符串)

go 语言中要定义一个多行字符串时,使用 反引号 (即键盘左上角数字一左侧的那个按键) 包裹。也叫原样字符串,输入啥样,输出就啥样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"fmt"
)

func main() {
s := `
床前明月光,
疑是地上霜。
举头望明月,
低头思故乡。
`
fmt.Printf("%s \n", s)
}

![](/note_image/Go/0 Go基础语法/pics/3-3-多行字符串.png)

1
2
3
4
5
6
7
8
9
10
11
package main

import (
"fmt"
)

func main() {
s := `D:\Go\src\code.github.cnoeng\stu`
// D:\Go\src\code.github.cnoeng\stu
fmt.Printf("%s \n", s)
}

3.4.3 字符串的常用操作

方法 含义
len(str) 获取字符串的长度
+ 或 fmt.Sprintf() 拼接字符串
strings.Split 分割
strings.contains 判断是否包含
strings.HasPrefixstrings.HasSuffix 前缀、后缀的判断
strings.Index()strings.LastIndex() 子串出现的位置
strings.Join(a[]string,sep string) join 操作 (拼接)

字符串是由 byte 字节组成,所以字符串的长度就是 byte 字节的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package main

import (
"fmt"
"strings"
)

func main() {
s := `张三`
// 6
fmt.Println(len(s))

// 字符串拼接
s1 := "李四"
// fmt.Printf 只能输出到终端
// 张三李四
fmt.Printf("%s \n", s+s1)
// 张三李四
fmt.Printf("%s%s \n", s, s1)
// fmt.Sprintf 可以将拼接后的值返回给变量
s2 := fmt.Sprintf("%s%s \n", s, s1)
// 张三李四
fmt.Printf("%s \n", s2)

// 字符串分割
s3 := "/Users/cnpeng/CnPeng/04_Demos/12_Go"
splitS := strings.Split(s3, "/")
// [ Users cnpeng CnPeng 04_Demos 12_Go]
fmt.Printf("%s \n", splitS)

// 是否包含——true
fmt.Println(strings.Contains(s2, "张三"))

// 前缀和后缀——true
fmt.Println(strings.HasPrefix(s2, "张"))
// true
fmt.Println(strings.HasSuffix(s2, "四"))

// 子串位置——0
fmt.Println(strings.Index(s2, "张"))
// 9
fmt.Println(strings.LastIndex(s2, "四"))

// Join 拼接——+Users+cnpeng+CnPeng+04_Demos+12_Go
fmt.Println(strings.Join(splitS, "+"))
}

3.4.4 byte 和 rune 类型

组成每个字符串的元素叫做字符。可以通过遍历或者单个获取字符串元素获得字符。字符使用单引号包裹,如:

1
2
var a := '中'
var b := 'x'

go 语言中的字符有如下两种:

  • uint8 类型,或者叫 byte 类型,代表了 ASCII 码的一个字符。
  • rune 类型,代表一个 UTF-8 字符。一个 rune 字符由一个或多个 byte 组成。

当需要处理中文、日文或其他复合字符时,需要使用 rune 类型。rune 类型实际是一个 int32

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"fmt"
)

func main() {
s := "中国"

// 普通遍历方式得到的是 byte ,最终输出结果为:228——ä184——¸173——­229——å155——›189——½
for i := 0; i < len(s); i++ {
fmt.Printf("%v——%c", s[i], s[i])
}

fmt.Println()

// range 遍历得到的数 rune ,最终结果为:20013——中22269——国
for _, c := range s {
fmt.Printf("%v——%c", c, c)
}
fmt.Println()
}

因为 UTF-8 编码下一个中文汉字由 3-4 个字节组成,所以我们不能简单的按照字节去遍历一个包含中文的字符串,否则就会出现上面第一个遍历中的结果。

3.4.5 修改字符串

字符串是不能直接修改的。

字符串底层是一个 byte 数组,所以可以和 []byte 类型相互转换。

修改字符串时,需要先将其转换成 []rune[]byte, 修改完成后再转换为 string。无论哪种转换都会重新分配内存,并复制字节数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
)

func main() {

s1 := "big"
byteS1 := []byte(s1)
byteS1[0] = 'p'
// pig
fmt.Println(string(byteS1))

s2 := "白萝卜"
runeS2 := []rune(s2)
runeS2[0] = '红'
//红萝卜
fmt.Println(string(runeS2))
}

3.5 类型转换和类型别名

3.5.1 类型转换

Go 语言中不允许隐式转换,所有类型转换必须显示声明,而且转换只能发生在两种相互兼容的类型之间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

func main() {
var a byte = 97
//显示类型转换
var b int = int(a)

//隐式类型转换,报错
// var c int = a

//类型不兼容,int 不能转为 bool
//var d bool = bool(b)
fmt.Println(d)
}

3.5.2 类型别名

  • 为现有的类型定义别名,方便调用。关键字 type

( 在 Swift 中也有这种类型别名,特别是对函数类型定义别名很有用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"

func main() {
//1、为 int64 起一个类型别名为,bigint
type bigint int64
var x bigint = 100

//2、同时定义多个类型别名
type (
myint int
mystr string
)

var y myint = 11
var z mystr = "12"

fmt.Println(x, y, z)
fmt.Printf("x,y,z 的类型分别为:%T , %T , %T \n ", x, y, z)
}

运行结果:

1
2
3
cnpeng$ go run Day1.go 
100 11 12
x,y,z 的类型分别为:main.bigint , main.myint , main.mystr

3.6 strconv 包

Go 语言中 strconv 包实现了基本数据类型和其字符串表示的相互转换。主要有以下常用函数: Atoi()Itoa()parse 系列、format 系列、append 系列。

更多函数请查看官方文档。

3.6.1 string与int类型转换

这一组函数是我们平时编程中用的最多的。

3.6.1.1 Atoi()

Atoi() 函数用于将字符串类型的整数转换为int类型,函数签名如下。

1
func Atoi(s string) (i int, err error)

如果传入的字符串参数无法转换为int类型,就会返回错误。

1
2
3
4
5
6
7
s1 := "100"
i1, err := strconv.Atoi(s1)
if err != nil {
fmt.Println("can't convert to int")
} else {
fmt.Printf("type:%T value:%#v\n", i1, i1) //type:int value:100
}

3.6.1.2 Itoa()

Itoa() 函数用于将 int 类型数据转换为对应的字符串表示,具体的函数签名如下。

1
func Itoa(i int) string

示例代码如下:

1
2
3
i2 := 200
s2 := strconv.Itoa(i2)
fmt.Printf("type:%T value:%#v\n", s2, s2) //type:string value:"200"

3.6.1.3 a的典故

这是 C 语言遗留下的典故。C 语言中没有 string 类型而是用字符数组(array)表示字符串,所以 Itoa 对很多 C 系的程序员很好理解。

3.6.2 Parse系列函数

Parse 类函数用于转换字符串为给定类型的值:ParseBool()ParseFloat()ParseInt()ParseUint()

3.6.2.1 ParseBool()

1
func ParseBool(str string) (value bool, err error)

返回字符串表示的 bool 值。

  • 当 str 为:1,t,T,TRUE,true,True 中的一种时为真值
  • 当 str 为:0,f,F,FALSE,false,False 中的一种时为假值
  • 其他输入内容一律返回 false
1
2
3
4
5
6
fmt.Println(strconv.ParseBool("t"))
fmt.Println(strconv.ParseBool("TRUE"))
fmt.Println(strconv.ParseBool("true"))
fmt.Println(strconv.ParseBool("True"))
fmt.Println(strconv.ParseBool("0"))
fmt.Println(strconv.ParseBool("f"))

3.6.2.2 ParseInt()

1
func ParseInt(s string, base int, bitSize int) (i int64, err error)

返回字符串表示的整数值,接受正负号。

  • base 指定进制(2到36),如果 base 为0,则会从字符串前置判断;0x 是16进制,0 是 8 进制,否则是 10 进制;

  • bitSize 指定结果必须能无溢出赋值的整数类型,0、8、16、32、64 分别代表 int、int8、int16、int32、int64;

  • 返回的 err 是 *NumErr 类型的,如果语法有误,err.Error = ErrSyntax;如果结果超出类型范围 err.Error = ErrRange

3.6.2.3 ParseUnit()

1
func ParseUint(s string, base int, bitSize int) (n uint64, err error)

ParseUint 类似 ParseInt 但不接受正负号,用于无符号整型。

3.6.2.4 ParseFloat()

1
func ParseFloat(s string, bitSize int) (f float64, err error)

解析一个表示浮点数的字符串并返回其值。

如果 s 合乎语法规则,函数会返回最为接近 s 表示值的一个浮点数(使用 IEEE754 规范舍入)。

  • bitSize 指定了期望的接收类型,32 是 float32(返回值可以不改变精确值的赋值给float32),64 是 float64;
  • 返回值 err 是 *NumErr 类型的,语法有误的,err.Error=ErrSyntax;结果超出表示范围的,返回值 f 为 ±Inferr.Error= ErrRange

3.6.2.5 代码示例

1
2
3
4
b, err := strconv.ParseBool("true")
f, err := strconv.ParseFloat("3.1415", 64)
i, err := strconv.ParseInt("-2", 10, 64)
u, err := strconv.ParseUint("2", 10, 64)

这些函数都有两个返回值,第一个返回值是转换后的值,第二个返回值为转化失败的错误信息。

3.6.3 Format系列函数

Format 系列函数实现了将给定类型数据格式化为 string 类型数据的功能。

3.6.3.1 FormatBool()

1
func FormatBool(b bool) string

根据 b 的值返回 "true""false"

3.6.3.2 FormatInt()

1
func FormatInt(i int64, base int) string

返回 i 的 base 进制的字符串表示。base 必须在2到36之间,当 base 大于 10 时,结果中会使用小写字母 az 表示大于 10 的数字。

3.6.3.3 FormatUint()

1
func FormatUint(i uint64, base int) string

是 FormatInt 的无符号整数版本。

3.6.3.4 FormatFloat()

1
func FormatFloat(f float64, fmt byte, prec, bitSize int) string

函数将浮点数表示为字符串并返回。

  • bitSize 表示 f 的来源类型(32:float32、64:float64),会据此进行舍入。
  • fmt 表示格式:f(-ddd.dddd)、b(-ddddp±ddd,指数为二进制)、e(-d.dddde±dd,十进制指数)、E(-d.ddddE±dd,十进制指数)、g(指数很大时用e格式,否则f格式)、G(指数很大时用E格式,否则f格式)。
  • prec 控制精度(排除指数部分):feE,它表示小数点后的数字个数;对 gG,它控制总的数字个数。如果 prec 为 -1,则代表使用最少数量的、但又必需的数字来表示 f 。

3.6.3.5 代码示例

1
2
3
4
s1 := strconv.FormatBool(true)
s2 := strconv.FormatFloat(3.1415, 'E', -1, 64)
s3 := strconv.FormatInt(-2, 16)
s4 := strconv.FormatUint(2, 16)

3.6.4 其他

3.6.4.1 isPrint()

1
func IsPrint(r rune) bool

返回一个字符是否是可打印的,和 unicode.IsPrint 一样,r 必须是:字母(广义)数字标点符号ASCII空格

3.6.4.2 CanBackquote()

1
func CanBackquote(s string) bool

返回字符串 s 是否可以不被修改的表示为一个单行的、没有空格tab之外控制字符反引号字符串

3.6.4.3 其他

除上文列出的函数外,strconv 包中还有 Append系列、Quote系列等函数。具体用法可查看官方文档。

更多函数请查看官方文档。