美好世界的多样性
整型
有符号整型 | 有符号整型取值范围 | 无符号整型 | 无符号整型取值范围 | 内存占用 |
---|---|---|---|---|
int8 | -2^7 ~ 2^7-1 | uint8 | 0 ~ 2^8-1 | 1 |
int16 | -2^15 ~ 2^15-1 | uint16 | 0 ~ 2^16-1 | 2 |
int32 | -2^31 ~ 2^31-1 | uint32 | 0 ~ 2^32-1 | 4 |
int64 | -2^63 ~ 2^63-1 | uint64 | 0 ~ 2^61-1 | 8 |
Tips
如果使用短变量定义法定义int类型,那么根据操作系统类型不同,int的类型也会相应改变。例如,64位操作系统,使用短变量定义法定义的int类型,就是int64,32位的操作系统定义就是int32。
美好总会互相流动
var a1 int32 = 10
var a2 int64 = 21
fmt.Println(int64(a1) + a2) // 低向高转换不需要考虑取值范围问题
fmt.Println(a1 + int32(a2)) // 高向低转换需要考虑取值范围问题
美好世界的新规则
Go1.13版本之后引入了数字字面量语法,这样便于开发者以二进制、八进制或十六进制浮点数的格式定义数字,例如:
v1 := 0b00101101 //代表二进制的101101,相当于十进制的45
v2 := 0o377 // 代表八进制的0377,相当于十进制的255
fmt.Println(v1, v2) // 输出常量,常量在程序运行期间不会改变
浮点型
Go语言支持两种浮点型数:float32
和float64
。
这两种浮点型数数据格式遵循IEEE 754标准:
float32
的浮点数的最大范围约为3.4e38
,可以使用常量定义:math.MaxFloat32
。
float64
的浮点数的最大范围约为1.8e308
,可以使用一个常量定义:math.MaxFloat64
打印浮点数时,可以使用fmt
包配合%f
,代码如下:
package main // 包名,main包是程序的入口,每个可执行程序都必须包含一个main包
import (
"fmt"
"math"
)
func main() {
fmt.Printf("%f\n", math.Pi) // 默认保留6位小数 3.141593
fmt.Printf("%.2f\n", math.Pi) // 保留2位小数 3.14
}
让美好多一种表现
用科学计数法表示浮点数
var f2 = 3.14e2 // 表示3.14*10^2
fmt.Printf("%f", f2) // 314.000000
var f3 = 3.14e-2 // 表示3.14*10^-2
fmt.Printf("%f", f3) // 0.031400
偶尔迷路的美好
几乎所有编程语言都有精度丢失问题,这是典型的二进制浮点数精度损失问题,在定长条件下,二进制小数和十进制小数互转都有可能有精度丢失。
// 浮点数精度丢失
d := 1129.6
fmt.Println(d * 100) // 112959.99999999999
m1 := 8.2
m2 := 3.7
fmt.Println(m1 - m2) // 4.499999999999999
布尔型
Go语言中以bool
类型进行声明布尔型数据,布尔型数据只有true
(真)、 false
(假)两个值
注意:
- 布尔类型变量的默认值为
false
- Go语言中不允许将整型强制转换为布尔型
- 布尔型无法参与数值运算,也无法与其他类型进行转换。
错误示范:
var a = 1
if a { // 编译错误,不能将int类型赋值给bool类型
fmt.Printf("true")
}
字符串
Go语言中的字符串以原生数据类型出现,使用字符串就像使用其他原生数据类型(int、bool、float等)一样。
Go语言里的字符串的内部实现使用UTF-8编码。
字符串的值为双引号中的内容,可以在Go语言的源码中直接添加非ASCII码字符,例如:
s1 := "你好,世界!"
s2 := "Hello World!"
var s3 = "hello golang!"
var s4 string = "你好,golang
换种方式表达美好
转义符 | 含义 |
---|---|
\r | 回车符(返回行首) |
\n | 换行符(直接跳到下一行的同列位置) |
\t | 制表符 |
\' | 单引号 |
\" | 双引号 |
\\ | 反斜杠 |
举例,打印Windows系统下的文件路径
str1 := "D:\\CODE\\GO_CODE" // \\反斜杠转义
fmt.Println(str1) // D:\CODE\GO_CODE
多行字符串
使用两个反引号``包裹字符串,即可实现多行字符串打印
var str1 = `hello
world`
fmt.Println(str1)
美好的多种打开方式
方法 | 介绍 |
---|---|
len() | 求字符串长度 |
+ 或者 fmt.Sprintf() | 拼接字符串 |
strings.Split() | 分割字符串 |
strings.Contains() | 判断母字符串是否包含子字符串 |
strings.HasPrefix(),strings.HasSuffix() | 字符串前缀/后缀判断 |
strings.Index(),strings.LastIndex() | 子字符串出现的位置 |
string.Join(a[]string,sep string) | 将字符串切片重组为字符串 |
求字符串长度
str1 := "hello world"
fmt.Println(len(str1)) // len()函数可以获取字符串的长度,16
拼接字符串
+
或者fmt.Spirntf
var str1 = "hello "
var str2 = "world"
fmt.Println(str1 + str2) // 字符串拼接,将str1和str2拼接起来,并打印
str3 := fmt.Sprintf("%v%v", str1, str2) // 格式化字符串,将str1和str2拼接起来,赋值给str3
fmt.Println(str3)
str4 := "hello" + // +号后面换行,表示字符串拼接
"world" +
"golang"
fmt.Println(str4) // 多行字符串,将字符串分成多行,最后拼接起来
注意:反引号间换行符将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出
分割字符串
strings.Split
package main // 包名,main包是程序的入口,每个可执行程序都必须包含一个main包
import (
"fmt"
"strings"
)
func main() {
s := "1-2-3"
fmt.Println(strings.Split(s, "-")) // 分割字符串,返回一个字符串切片,切片是引用类型,和数组类似,但是长度不固定
}
将字符串切片重组为字符串
strings.Join
package main // 包名,main包是程序的入口,每个可执行程序都必须包含一个main包
import (
"fmt"
"strings"
)
func main() {
s := "1-2-3"
s1 := strings.Split(s, "-") // 按-分割,返回一个字符串切片
s2 := strings.Join(s1, "+") // 按照指定的连接符连接字符串切片,返回一个字符串
fmt.Println(s2)
}
字符串包含
strings.Contains
package main // 包名,main包是程序的入口,每个可执行程序都必须包含一个main包
import (
"fmt"
"strings"
)
func main() {
s := "this is str"
s1 := "this"
flag := strings.Contains(s, s1) // 判断s中是否包含s1,返回bool值
fmt.Println(flag)
}
字符串前缀/后缀判断
strings.HasPrefix //前缀
strings.HasSuffix //后缀
package main // 包名,main包是程序的入口,每个可执行程序都必须包含一个main包
import (
"fmt"
"strings"
)
func main() {
s := "this is str"
s1 := "this"
flag1 := strings.HasPrefix(s, s1) // 判断字符串s是否以s1开头,返回bool值
fmt.Println(flag1)
flag2 := strings.HasSuffix(s, s1) // 判断字符串s是否以s1结尾,返回bool值
fmt.Println(flag2)
}
子字符串出现的位置
strings.Index // 获取子字符串在母字符串中的位置,没有则返回-1,从0开始,从前往后找
strings.LastIndex // 获取子字符串在母字符串中的位置,没有则返回-1,从0开始,后往前找
package main // 包名,main包是程序的入口,每个可执行程序都必须包含一个main包
import (
"fmt"
"strings"
)
func main() {
s := "this is str"
s1 := "is"
flag1 := strings.Index(s, s1) // 获取s1在s中的位置,没有则返回-1,从0开始,从前往后找
fmt.Println(flag1)
flag2 := strings.LastIndex(s, s1) // 获取s1在s中的最后一个位置,没有则返回-1,从0开始,从后往前找
fmt.Println(flag2)
}
字符
golang中的字符用单引号定义,单引号中只能写入一个字符,并且字符属于int32类型。
byte型
uint8
类型,或者叫byte
型,代表了ASCII码中的一个字符。
package main
import (
"fmt"
)
func main() {
a := 'a' // 字符类型,占用4个字节,范围-128~127,0~255,使用单引号,使用int32类型
fmt.Printf("a --> %T\n", a) // %T 打印变量类型,int32
fmt.Printf("a --> %v\n", a) // %v 打印变量值,97,是字符对应的ascii码值
fmt.Printf("a --> %c\n", a) // %c 打印字符a,而不是97
}
rune类型
rune
类型代表一个UTF-8类型
当需要处理中文、日文或其他符合字符时,则需要用到rune类型
。rune类型
实际是一个int32
。
Go使用了特殊的rune类型
来处理Unicode
,让基于Unicode的文本处理更为方便,也可以使用byte型进行默认字符串处理,性能和扩展性都有照顾。
Go中一个汉字占用三个字节,一个字母占用一个字节。
package main
import (
"fmt"
)
func main() {
str := "world"
fmt.Printf("%v\n", str[3]) // 输出:108
fmt.Printf("%T\n", str[4]) // 输出:uint8 (字符串的索引类型为int)
fmt.Printf("%c\n", str[0]) // 输出:w
}
package main
import (
"fmt"
)
func main() {
str := "world"
fmt.Println(len(str)) // 5
s := "好"
fmt.Println(len(s)) // 3
}
Go中汉字用的是Unicode编码
package main
import (
"fmt"
)
func main() {
s := '好'
fmt.Printf("%v\n", s) //22909 汉字用的是unicode编码值
}
修改字符串
Go中修改字符串,需要先把字符串转换成字节数组,通过修改字节数组的值从而改变字符串对应的值,再将修改后的字节数组转换成字符串输出。
修改英文字符串
英文字符串转换成byte类型
package main
import (
"fmt"
)
func main() {
s1 := "hello" //英文字符串转换成byte
byteStr := []byte(s1) // 将字符串转换为字节数组,每个字符对应一个字节,一个汉字对应3个字节
byteStr[0] = 'H' // 修改字节数组中的值,会改变字符串的值
fmt.Println(string(byteStr)) // 将字节数组转换为字符串,输出:Hello
}
修改中文字符串
中文字符串转换成rune类型
package main
import (
"fmt"
)
func main() {
s2 := "你好" //中文字符串转换成rune
runeStr := []rune(s2) // 将字符串转换为rune数组,每个字符对应一个rune,一个汉字对应一个rune
runeStr[0] = '我' // 修改rune数组中的值,会改变字符串的值
fmt.Println(string(runeStr)) // 将rune数组转换为字符串,输出:我好
}