3 基本数据类型
基本数据类型包括:整型、浮点型、布尔型、字符串。
除以上基本类型之外,还有 数组、切片、结构体、函数、map、通道 等。
3.1 整型
3.1.1 整型
整型分为:int8
、int16
、int32
、int64
,以及对应的无符号整型:uint8
、uint16
、uint32
、uint64
其中 unit8
对应其他语言中的 byte
类型;int16
对应 C 语言中的 short
类型;int64
对应 C 语言中的 long
类型。
各数据类型及对应的取值关系如下:
特殊整型:
注意: 获取对象的长度时,内建的
len()
函数返回的长度可以根据不同平台的字节长度进行变化。实际使用中,切片或 map 的元素数量等都可以直接使用 int 来表示 。
3.1.2 八进制和十六进制
go
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 语言支持两种浮点型数,float32
和 float64
.
这两种浮点型数据格式遵循 IEEE 754
标准, float32 的浮点数的最大范围约为 3.4e38
,可以使用常量定义:math.MaxFloat32
。float64 的浮点数的最大范围约为 1.8e308
, 可以使用常量定义 math.MaxFloat64
go
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(复数)
可以获取虚部- 有
complex64
和complex128
两种类型,complex64 的实部和虚部为 32 位,complex128 的实部和虚部为 64 位。
go
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))
}
运行结果:
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
声明布尔类型数据。布尔类型仅有 true
和 false
两种值。
注意:
- 布尔类型变量的默认值为 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 使用大写 |
go
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 编码的汉字通常占用三个字节,偏僻字可能会占四个字节。
go
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 语言中要定义一个多行字符串时,使用 反引号
(即键盘左上角数字一左侧的那个按键) 包裹。也叫原样字符串,输入啥样,输出就啥样。
go
package main
import (
"fmt"
)
func main() {
s := `
床前明月光,
疑是地上霜。
举头望明月,
低头思故乡。
`
fmt.Printf("%s \n", s)
}
go
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.HasPrefix 、strings.HasSuffix |
前缀、后缀的判断 |
strings.Index() 、strings.LastIndex() |
子串出现的位置 |
strings.Join(a[]string,sep string) |
join 操作 (拼接) |
字符串是由 byte 字节组成,所以字符串的长度就是 byte 字节的长度。
go
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 类型
组成每个字符串的元素叫做字符。可以通过遍历或者单个获取字符串元素获得字符。字符使用单引号包裹,如:
go
var a := '中'
var b := 'x'
go 语言中的字符有如下两种:
uint8
类型,或者叫byte
类型,代表了 ASCII 码的一个字符。rune
类型,代表一个UTF-8
字符。一个rune
字符由一个或多个 byte 组成。
当需要处理中文、日文或其他复合字符时,需要使用 rune
类型。rune
类型实际是一个 int32
go
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。无论哪种转换都会重新分配内存,并复制字节数组。
go
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 语言中不允许隐式转换,所有类型转换必须显示声明,而且转换只能发生在两种相互兼容的类型之间。
go
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 中也有这种类型别名,特别是对函数类型定义别名很有用)
go
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)
}
运行结果:
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类型,函数签名如下。
go
func Atoi(s string) (i int, err error)
如果传入的字符串参数无法转换为int类型,就会返回错误。
go
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 类型数据转换为对应的字符串表示,具体的函数签名如下。
go
func Itoa(i int) string
示例代码如下:
go
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()
go
func ParseBool(str string) (value bool, err error)
返回字符串表示的 bool 值。
- 当 str 为:1,t,T,TRUE,true,True 中的一种时为真值
- 当 str 为:0,f,F,FALSE,false,False 中的一种时为假值
- 其他输入内容一律返回 false
go
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()
go
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()
go
func ParseUint(s string, base int, bitSize int) (n uint64, err error)
ParseUint 类似 ParseInt 但不接受正负号,用于无符号整型。
3.6.2.4 ParseFloat()
go
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 为±Inf
,err.Error= ErrRange
。
3.6.2.5 代码示例
go
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()
go
func FormatBool(b bool) string
根据 b 的值返回 "true"
或 "false"
。
3.6.3.2 FormatInt()
go
func FormatInt(i int64, base int) string
返回 i 的 base 进制的字符串表示。base
必须在2到36之间,当 base 大于 10 时,结果中会使用小写字母 a
到 z
表示大于 10 的数字。
3.6.3.3 FormatUint()
go
func FormatUint(i uint64, base int) string
是 FormatInt 的无符号整数版本。
3.6.3.4 FormatFloat()
go
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
控制精度(排除指数部分):对f
、e
、E
,它表示小数点后的数字个数;对g
、G
,它控制总的数字个数。如果 prec 为 -1,则代表使用最少数量的、但又必需的数字来表示 f 。
3.6.3.5 代码示例
go
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()
go
func IsPrint(r rune) bool
返回一个字符是否是可打印的,和 unicode.IsPrint
一样,r 必须是:字母(广义)
、数字
、标点
、符号
、ASCII空格
。
3.6.4.2 CanBackquote()
go
func CanBackquote(s string) bool
返回字符串 s 是否可以不被修改的表示为一个单行的、没有空格
和 tab之外控制字符
的反引号字符串。
3.6.4.3 其他
除上文列出的函数外,strconv 包中还有 Append
系列、Quote
系列等函数。具体用法可查看官方文档。