03-Go语言之数据类型
内容目录
- 整型
- 浮点类型
- 复数
- 布尔值
- 字符串
- byte类型和rune类型
- if循环
内容详细
整型
-
整型分为以下两个大类: 按长度分为:int8、int16、int32、int64 对应的无符号整型:uint8、uint16、uint32、uint64
其中,
uint8
就是我们熟知的byte
型,int16
对应C语言中的short
型,int64
对应C语言中的long
型。类型 描述 uint8 无符号 8位整型 (0 到 255) uint16 无符号 16位整型 (0 到 65535) uint32 无符号 32位整型 (0 到 4294967295) uint64 无符号 64位整型 (0 到 18446744073709551615) int8 有符号 8位整型 (-128 到 127) int16 有符号 16位整型 (-32768 到 32767) int32 有符号 32位整型 (-2147483648 到 2147483647) int64 有符号 64位整型 (-9223372036854775808 到 9223372036854775807) -
特殊整型
类型 描述 uint 32位操作系统上就是 uint32
,64位操作系统上就是uint64
int 32位操作系统上就是 int32
,64位操作系统上就是int64
uintptr 无符号整型,用于存放一个指针
注意: 在使用int
和 uint
类型时,不能假定它是32位或64位的整型,而是考虑int
和uint
可能在不同平台上的差异。
注意事项 获取对象的长度的内建len()
函数返回的长度可以根据不同平台的字节长度进行变化。实际使用中,切片或 map 的元素数量等都可以用int
来表示。在涉及到二进制传输、读写文件的结构描述时,为了保持文件的结构不会受到不同编译目标平台字节长度的影响,不要使用int
和 uint
。
数字字面量语法
-
Go1.13版本之后引入了数字字面量语法,这样便于开发者以二进制、八进制或十六进制浮点数的格式定义数字
-
v := 0b00101101
, 代表二进制的 101101,相当于十进制的 45。v := 0o377
,代表八进制的 377,相当于十进制的 255。v := 0x1p-2
,代表十六进制的 1 除以 2²,也就是 0.25。 -
而且还允许我们用
_
来分隔数字,比如说:v := 123_456
表示 v 的值等于 123456。package main import "fmt" func main() { // 十进制 var a int = 10 fmt.Printf("%d \n",a) // 占位符%d表示10进制:10 fmt.Printf("%b \n",a) // 占位符%b表示2进制:1010 // 八进制 以0开头 var b int = 077 fmt.Printf("%o \n",b) // 77 // 十六进制 以0x开头 var c int = 0xff fmt.Printf("%x \n",c) // ff fmt.Printf("%X \n",c) // FF // 变量的内存地址 fmt.Printf("%p \n", &a) // 占位符%p表示十六进制的内存地址:0xc00009c058 }
浮点类型
-
Go语言支持两种浮点型数:
float32
和float64
。这两种浮点型数据格式遵循IEEE 754
标准:float32
的浮点数的最大范围约为3.4e38
,可以使用常量定义:math.MaxFloat32
。float64
的浮点数的最大范围约为1.8e308
,可以使用一个常量定义:math.MaxFloat64
。打印浮点数时,可以使用
fmt
包配合动词%f
,代码如下:package main import ( "fmt" "math" // 导入多个包 ) func main() { fmt.Printf("%f\n", math.Pi) fmt.Printf("%.2f\n", math.Pi) }
-
浮点型做运算:因为有
IEEE784
的标准,所有的浮点数运算都不精确- 转换成字符串去做运算
- 整体放大多少倍去做运算
复数
-
complex64和complex128
-
复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位。
var c1 complex64 c1 = 1 + 2i var c2 complex128 c2 = 2 + 3i fmt.Println(c1) // 结果为(1+2i) fmt.Println(c2) // 结果为(2+3i)
布尔值
- Go语言中以
bool
类型进行声明布尔型数据,布尔型数据只有true(真)
和false(假)
两个值。 - 注意:
- 布尔类型变量的默认值为
false
。 - Go 语言中不允许将整型强制转换为布尔型.
- 布尔型无法参与数值运算,也无法与其他类型进行转换。
- 布尔类型变量的默认值为
字符串
- Go 语言里的字符串的内部实现使用
UTF-8
编码。 字符串的值为双引号(")
中的内容,可以在Go语言的源码中直接添加非ASCII码字符,例如:
s1 := "hello"
s2 := "你好"
字符串转义符
-
Go 语言的字符串常见转义符包含回车、换行、单双引号、制表符等,如下表所示。
转义符 含义 \r
回车符(返回行首) \n
换行符(直接跳到下一行的同列位置) \t
制表符 \'
单引号 \"
双引号 \\
反斜杠 -
举个例子,我们要打印一个Windows平台下的一个文件路径:
package main import ( "fmt" ) func main() { fmt.Println("str := \"c:\\Code\\lesson1\\go.exe\"") // 结果是str := "c:\Code\lesson1\go.exe" }
多行字符串
-
Go语言中要定义一个多行字符串时,就必须使用
反引号
字符: -
反引号间换行将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出。
s1 := `第一行 第二行 第三行 ` fmt.Println(s1)
字符串常用操作
方法 | 介绍 |
---|---|
len(str) |
求长度 |
+或fmt.Sprintf |
拼接字符串 |
strings.Split |
分割 |
strings.contains |
判断是否包含 |
strings.HasPrefix,strings.HasSuffix |
前缀/后缀判断 |
strings.Index(),strings.LastIndex() |
子串出现的位置 |
strings.Join(a[]string, sep string) |
join操作 |
package main
import (
"fmt"
"strings"
)
func main() {
// 计算字符串长度
s1:="golangisgood"
fmt.Println(len(s1)) // 计算s1的字符串长度:12
// 字符串拼接
s2:="python"
fmt.Println(s1+s2) // 使用+号把字符串拼接:golangisgoodpython
s3:= fmt.Sprintf("%s----%s",s1,s2)
fmt.Println(s3) // 使用Sprintf占位符拼接:golangisgood----python
// 分割
ret := strings.Split(s1,"is")
fmt.Println(ret) // 分割:[golang good]
// 判断是否包含
ret2 := strings.Contains(s1,"is")
fmt.Println(ret2) // true
// 判断前缀和后缀
ret3 := strings.HasPrefix(s1,"go") // 判断go是否是s1的前缀:true
ret4 := strings.HasSuffix(s1,"is") // 判断is是否是s1的后缀:false
fmt.Println(ret3,ret4)
// 求子串的位置
s4 := "applepen"
fmt.Println(strings.Index(s4,"p")) // 求第一个出现p的位置:1
fmt.Println(strings.LastIndex(s4,"p"))// 求最后一个出现p的位置:5
// join组合
a1 := []string{"Python","PHP","JavaScript","Ruby","Golang"}
fmt.Println(strings.Join(a1,"-")) // 把所有字符串用——拼接在一起:Python-PHP-JavaScript-Ruby-Golang
}
byte和rune类型
-
组成每个字符串的元素叫做“字符”,可以通过遍历或者单个获取字符串元素获得字符。 字符用单引号(’)包裹起来
var a := '中' var b := 'x'
-
Go 语言的字符有以下两种:
uint8
类型,或者叫 byte 型,代表了ASCII码
的一个字符。rune
类型,代表一个UTF-8字符
。
-
当需要处理中文、日文或者其他复合字符时,则需要用到
rune
类型。rune
类型实际是一个int32
。func main() { s1 := "Golang" c1 := 'G' // ASCII码下占一个字节(8位,8bit) fmt.Println(s1,c1) // Golang 71 s2 := "中国" c2 := '中' // UTF-8编码下一个中文占3个字节 fmt.Println(s2,c2) // 中国 20013 s3 := "hello中国" fmt.Println(len(s3)) // 因为每个中文字符占3个字节,所以5+6=11,长度为11 }
-
Go 使用了特殊的 rune 类型来处理 Unicode,让基于 Unicode 的文本处理更为方便,也可以使用 byte 型进行默认字符串处理,性能和扩展性都有照顾。
func main() { s := "hello沙河" // 遍历每个字节,包括中文字节,会把中文字节拆分成3个字节 for i := 0; i < len(s); i++ { //byte fmt.Printf("%v(%c) ", s[i], s[i]) } fmt.Println() // for range 循环,是按照rune类型去遍历的 for _, r := range s { //rune fmt.Printf("%v(%c) ", r, r) } fmt.Println() } // 输出为: 104(h) 101(e) 108(l) 108(l) 111(o) 230(æ) 178(²) 153() 230(æ) 178(²) 179(³) 104(h) 101(e) 108(l) 108(l) 111(o) 27801(沙) 27827(河)
修改字符串
-
要修改字符串,需要先将其转换成
[]rune
或[]byte
,完成后再转换为string
。无论哪种转换,都会重新分配内存,并复制字节数组。func main() { // 强制类型转换 s5 := "big" // 将字符串强制转换成字节数组类型 byterArray := []byte(s5) fmt.Println(byterArray) // [98 105 103] byterArray[0] = 'p' fmt.Println(byterArray) // [112 105 103] // 将字节数组强制转换成字符串类型 s5 = string(byterArray) fmt.Println(s5) // pig }
-
示例:字符串反转
// 方式一: func main() { s1 := "hello" byteArray :=[]byte(s1) s2 := "" for i :=len(byteArray)-1;i>=0;i--{ s2 += string(byteArray[i]) } fmt.Println(s2) } // 方式二: func main() { s1 := "hello" byteArray :=[]byte(s1) length := len(byteArray)-1 for i :=0;i<=length/2;i++{ byteArray[i],byteArray[length-i] = byteArray[length-i],byteArray[i] } fmt.Println(string(byteArray)) }
if条件判断
- Go语言中最常用的流程控制有
if
和for
,而switch
和goto
主要是为了简化代码、降低重复代码而生的结构,属于扩展类的流程控制。
if条件判断基本写法
-
Go语言中if条件判断的格式:
-
注意:大括号必须跟
if
在同一行if 表达式1{ 执行语句1 }else if 表达式2{ 执行语句2 }else{ 执行语句3 }
if条件判断特殊写法
-
if条件判断还有一种特殊的写法,可以在
if
表达式之前添加一个执行语句,再根据变量值进行判断 -
此变量只在
if
作用域中生效,if
语句执行完毕后回收内存func ifDemo(){ if score := 65;score >= 90{ fmt.Println("A") }else if score>=75{ fmt.Println("B") }else { fmt.Println("C") } }
for循环
-
Go 语言中的所有循环类型均可以使用
for
关键字来完成。 -
for循环的基本格式:
-
条件表达式返回
true
时循环体不停地进行循环,直到条件表达式返回false
时自动退出循环。for 初始语句;条件表达式;结束语句{ 循环体语句 } // 例1: func forDemo() { for i := 0; i < 10; i++ { fmt.Println(i) } } // 例2: func forDemo1(){ for num,i:= 10,1; i<10 && num<=18; i, num = i+1, num+1 { fmt.Printf("%d * %d = %d\n", num, i, num*i) } }
-
for循环的初始语句可以被忽略,但是初始语句后的分号必须要写,例如:
func forDemo2() { i := 0 for ; i < 10; i++ { fmt.Println(i) } }
-
for循环的初始语句和结束语句都可以省略
func forDemo3() { i := 0 for i < 10 { fmt.Println(i) i++ } }
这种写法类似于其他编程语言中的
while
,在while
后添加一个条件表达式,满足条件表达式时持续循环,否则结束循环。
无限循环
-
for循环可以通过
break
、goto
、return
、panic
语句强制退出循环。for { 循环体语句 }
for range(键值循环)
- Go语言中可以使用
for range
遍历数组、切片、字符串、map 及通道(channel)。 通过for range
遍历的返回值有以下规律:-
数组、切片、字符串返回索引和值。
-
map返回键和值。
-
通道(channel)只返回通道内的值。
import "fmt" func switchDemo1() { // 只是英文字符 s := "abc" for i:=range s{ fmt.Printf("下标=%d,值=%c; ",i,s[i]) } fmt.Println() // 带中文字符的 z := "我爱你中国" for i,c :=range z{ fmt.Printf("下标=%d, 值=%c; ",i,c) } } func main() { switchDemo1() } // 下标=0,值=a; 下标=1,值=b; 下标=2,值=c; // 下标=0, 值=我; 下标=3, 值=爱; 下标=6, 值=你; 下标=9, 值=中; 下标=12, 值=国;
-
switch case
-
使用
switch
语句可方便地对大量的值进行条件判断。 -
Go语言规定每个
switch
只能有一个default
分支。func switchDemo1() { finger := 3 // 条件语句 switch finger { case 1: fmt.Println("大拇指") case 2: fmt.Println("食指") case 3: fmt.Println("中指") case 4: fmt.Println("无名指") case 5: fmt.Println("小拇指") default: fmt.Println("无效的输入!") } }
-
一个分支可以有多个值,多个case值中间使用英文逗号隔开
func testSwitch3() { switch n := 7; n { case 1, 3, 5, 7, 9: fmt.Println("奇数") case 2, 4, 6, 8: fmt.Println("偶数") default: fmt.Println(n) } }
-
分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量
func switchDemo4() { age := 30 switch { case age < 25: fmt.Println("好好学习吧") case age > 25 && age < 35: fmt.Println("好好工作吧") case age > 60: fmt.Println("好好享受吧") default: fmt.Println("活着真好") } }
-
fallthrough
语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的func switchDemo5() { s := "a" switch { case s == "a": // 成立后 fmt.Println("a") fallthrough // 无条件的执行下一个case case s == "b": fmt.Println("b") case s == "c": fmt.Println("c") default: fmt.Println("...") } } // 结果是a,b
break和continue
-
break:终止此次循环
-
break
语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的for
、switch
和select
的代码块上。func breakDemo1() { BREAKDEMO1: for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { if j == 2 { break BREAKDEMO1 // break后面跟标签,可以终止标签中整个for循环 } fmt.Printf("%v-%v\n", i, j) } } fmt.Println("...") }
-
continue:跳过当次循环
-
在
continue
语句后添加标签时,表示开始标签对应的循环。func continueDemo() { forloop1: for i := 0; i < 5; i++ { // forloop2: for j := 0; j < 5; j++ { if i == 2 && j == 2 { continue forloop1 // 加上标签,可以控制从哪开始继续循环 } fmt.Printf("%v-%v\n", i, j) } } }
goto跳转到指定位置
-
可以跳转到指定位置
func gotoDemo() { for i := 0;i<5;i++{ goto LABEL fmt.Println("for循环内") } fmt.Println("for循环外") LABEL: fmt.Println("跳转到goto执行语句中") } // 结果是 "跳转到goto执行语句中"