Go语言同时提供了有符号和无符号的整数类型。
- 有符号整型:int、int8、int64、int32、int64
- 无符号整型:uint、uint8、uint64、uint32、uint64、uintptr
有符号整型范围:-2^(n-1) 到 2^(n-1)-1
无符号整型范围: 0 到 2^n-1
实际开发中由于编译器和计算机硬件的不同,int 和 uint 所能表示的整数大小会在 32bit 或 64bit 之间变化。
uint在硬件开发中使用
用来表示 Unicode 字符的 rune 类型和 int32 类型是等价的,通常用于表示一个 Unicode 码点。这两个名称可以互换使用。同样,byte 和 uint8 也是等价类型,byte 类型一般用于强调数值是一个原始的数据而不是一个小的整数。
无符号的整数类型 uintptr,它没有指定具体的 bit 大小但是足以容纳指针。uintptr 类型只有在底层编程时才需要,特别是Go语言和C语言函数库或操作系统接口相交互的地方。
在二进制传输、读写文件的结构描述时,为了保持文件的结构不会受到不同编译目标平台字节长度的影响,不要使用 int 和 uint
- 浮点型
Go语言支持两种浮点型数:
float32 : 范围 约1.4e-45 到 约3.4e38
float64 :范围约4.9e-324 到 约1.8e308
func main() {myfloat := 3.2//%.2f 保留两位小数fmt.Printf("%.2f", myfloat) //3.20
}
通常应该优先使用 float64 类型,因为 float32 类型的累计计算误差很容易扩散,并且 float32 能精确表示的正整数并不是很大。
var f float32 = 1 << 24fmt.Println(f == f+1) //true
当这个整数赋值给float32类型的变量f时,会发生类型转换。由于16777216超过了float32能够精确表示的最大正整数(大约是3.4028235E+38),这个转换会导致精度损失。实际上,16777216会被转换为1.6777216e+07(即16777216.0),但这个转换并不是精确的,因为float32只有7位有效数字。
因此,当你对f加1时,你其实是在对1.6777216e+07加1,但由于精度限制,结果仍然是1.6777216e+07。所以,f和f+1在float32的表示中是相等的,因此f == f+1的结果是true。
浮点数在声明的时候可以只写整数部分或者小数部分
a := .12341b := 1.fmt.Printf("%.5f,%1.f", a, b)
3. 布尔型
在Go语言中,以bool类型进行声明:
var 变量名 bool
1
==,>,<,<=, >=,&&(AND),||(OR)等都会产生bool值
var aVar = 10
aVar == 5 // false
aVar == 10 // true
aVar != 5 // true
aVar != 10 // false
1
Go语言对于值之间的比较有非常严格的限制,只有两个相同类型的值才可以进行比较,如果值的类型是接口(interface),那么它们也必须都实现了相同的接口。
如果其中一个值是常量,那么另外一个值可以不是常量,但是类型必须和该常量类型相同。
如果以上条件都不满足,则必须将其中一个值的类型转换为和另外一个值的类型相同之后才可以进行比较。
&&(AND),||(OR)是具有短路行为的,如果运算符左边的值已经可以确定整个布尔表达式的值,那么运算符右边的值将不再被求值。(&&优先级高于||)
var a = 10//因为a>11已经不满足了,所以a < 30不会走,整个表达式为falseif(a > 11 && a < 30){fmt.Println("正确")}else{fmt.Println("错误")}//因为a > 5已经满足了,所以a < 30不会走,整个表达式为trueif(a > 5 || a < 30){fmt.Println("正确")}else{fmt.Println("错误")}
布尔型数据只有true和false,且不能参与任何计算以及类型转换
4. 字符类型
Go语言的字符有以下两种:
- 一种是 uint8 类型,或者叫 byte 型,代表了 ASCII 码的一个字符。
- 另一种是 rune 类型,代表一个 UTF-8 字符,当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。rune 类型等价于 int32 类型。
byte 类型是 uint8 的别名,rune 类型是int32的别名
ASCII 码的一个字符占一个字节
ASCII 定义 128 个字符,由码位 0 – 127 标识。它涵盖英文字母,拉丁数字和其他一些字符。
字符的定义:
Unicode 是 ASCII 的超集,它定义了 1,114,112 个代码点的代码空间。 Unicode 版本 10.0 涵盖 139 个现代和历史文本集(包括符文字母,但不包括 Klingon )以及多个符号集。
Go语言同样支持 Unicode(UTF-8), 用rune来表示, 在内存中使用 int 来表示。
在书写 Unicode 字符时,需要在 16 进制数之前加上前缀\u或者\U。如果需要使用到 4 字节,则使用\u前缀,如果需要使用到 8 个字节,则使用\U前缀。
Unicode 包中内置了一些用于测试字符的函数,这些函数的返回值都是一个布尔值,如下所示(其中 ch 代表字符):
- 判断是否为字母:unicode.IsLetter(ch)
- 判断是否为数字:unicode.IsDigit(ch)
- 判断是否为空白符号:unicode.IsSpace(ch)
4.1 UTF-8 和 Unicode 有何区别?
Unicode 与 ASCII 类似,都是一种字符集。
字符集为每个字符分配一个唯一的 ID,我们使用到的所有字符在 Unicode 字符集中都有一个唯一的 ID,例如 a 在 Unicode 与 ASCII 中的编码都是 97。汉字“你”在 Unicode 中的编码为 20320,在不同国家的字符集中,字符所对应的 ID 也会不同。而无论任何情况下,Unicode 中的字符的 ID 都是不会变化的。
UTF-8 是编码规则,将 Unicode 中字符的 ID 以某种方式进行编码,UTF-8 的是一种变长编码规则,从 1 到 4 个字节不等。编码规则如下:
- 0xxxxxx 表示文字符号 0~127,兼容 ASCII 字符集。
- 从 128 到 0x10ffff 表示其他字符。
根据这个规则,拉丁文语系的字符编码一般情况下每个字符占用一个字节,而中文每个字符占用 3 个字节。
广义的 Unicode 指的是一个标准,它定义了字符集及编码规则,即 Unicode 字符集和 UTF-8、UTF-16 编码等
5. 字符串型
一个字符串是一个不可改变的字节序列,字符串可以包含任意的数据,但是通常是用来包含可读的文本,字符串是 UTF-8 字符的一个序列。
字符串的定义:
var mystr string = "hello"
1
go语言从底层就支持UTF-8编码。
UTF-8 是一种被广泛使用的编码格式,是文本文件的标准编码。
由于该编码对占用字节长度的不定性,在Go语言中字符串也可能根据需要占用 1 至 4 个字节,这与其它编程语言不同。
Go语言这样做不仅减少了内存和硬盘空间占用,同时也不用像其它语言那样需要对使用 UTF-8 字符集的文本进行编码和解码。
字符串是一种值类型,且值不可变,即创建某个文本后将无法再次修改这个文本的内容。
当字符为 ASCII 码表上的字符时则占用 1 个字节
字符串中可以使用转义字符来实现换行、缩进等效果,常用的转义字符包括:
- \n:换行符
- \r:回车符
- \t:tab 键
- \u 或 \U:Unicode 字符
- \:反斜杠自身
var str string = "hahahah"fmt.Println(str)
如果使用``反引号,会被原样进行赋值和输出
var str string = `\thahahah`fmt.Println(str) //\thahahah
字符串是字节的定长数组,byte 和 rune 都是字符类型,若多个字符放在一起,就组成了字符串
比如 hello ,对照 ascii 编码表,每个字母对应的编号是:104,101,108,108,111
var mystr01 string = "hello"var mystr02 [5]byte = [5]byte{104, 101, 108, 108, 111}fmt.Printf("myStr01: %s\n", mystr01)fmt.Printf("myStr02: %s", mystr02) //myStr02: hello
var str string = "hello,你好呀"//中文三字节,字母一个字节fmt.Println("len:", len(str)) //15
5.1 字符串的应用
一般的比较运算符(==、!=、<、<=、>=、>)是通过在内存中按字节比较来实现字符串比较的,因此比较的结果是字符串自然编码的顺序。
字符串所占的字节长度可以通过函数 len() 来获取,例如 len(str)。
字符串的内容(纯字节)可以通过标准索引法来获取,在方括号[ ]内写入索引,索引从 0 开始计数:
- 字符串 str 的第 1 个字节:str[0]
- 第 i 个字节:str[i - 1]
- 最后 1 个字节:str[len(str)-1]
需要注意的是,这种转换方案只对纯 ASCII 码的字符串有效。
注意:获取字符串中某个字节的地址属于非法行为,例如 &str[i]。
ASCII字符使用len()函数
Unicode字符串长度使用utf8.RuneCountInString()函数
var str string = "hello,你好呀"fmt.Println("len:", len(str)) //15fmt.Println(utf8.RuneCountInString(str)) //9
字符串拼接符“+”
两个字符串 s1 和 s2 可以通过 s := s1 + s2 拼接在一起。将 s2 追加到 s1 尾部并生成一个新的字符串 s,也可以使用“+=”来对字符串进行拼接:
var str string = "hello,你好呀,"var str2 string = "大帅哥"fmt.Println(str + str2) //hello,你好呀,大帅哥
除了使用+进行拼接,我们也可以使用WriteString()
如果从字符串 hello 码神之路 中获取 码 该如何获取呢?
直接索引对rune类型无效,可以使用string方法转换
var str string = "hello 码神之路"fmt.Println(string([]rune(str)[6]))
遍历
unicode字符集使用for range进行遍历,ascii字符集可以使用for range或者for循环遍历
var str string = "hello 码神之路"for _, val := range str {fmt.Println(string(val))}for _, val := range str {fmt.Printf("%c", val) //hello 码神之路}
字符串的格式化
- print : 结果写到标准输出
- Sprint:结果会以字符串形式返回
var str string = "hello "var str2 string = "大帅哥"var stringBuilder bytes.BufferstringBuilder.WriteString(str)stringBuilder.WriteString(str2)res := fmt.Sprintf(stringBuilder.String())fmt.Println(res)
%c 单一字符
%T 动态类型
%v 本来值的输出
%+v 字段名+值打印
%d 十进制打印数字
%p 指针,十六进制
%f 浮点数
%b 二进制
%s string
字符串查找
如何获取字符串中的某一段字符?
- strings.Index(): 正向搜索子字符串
- strings.LastIndex():反向搜索子字符串
trace := "哈哈哈,你好天涯"index := strings.Index(trace, ",")fmt.Println(index) //9lastIndex := strings.LastIndex(trace, "涯")fmt.Println(lastIndex) //19
6. 类型转换
在必要以及可行的情况下,一个类型的值可以被转换成另一种类型的值。由于Go语言不存在隐式类型转换,因此所有的类型转换都必须显式的声明
a := 5.0
b := int(a)
类型转换只能在定义正确的情况下转换成功,例如从一个取值范围较小的类型转换到一个取值范围较大的类型(将 int16 转换为 int32)。
当从一个取值范围较大的类型转换到取值范围较小的类型时(将 int32 转换为 int16 或将 float32 转换为 int),会发生精度丢失的情况。
只有相同底层类型的变量之间可以进行相互转换(如将 int16 类型转换成 int32 类型),不同底层类型的变量相互转换时会引发编译错误(如将 bool 类型转换为 int 类型):
浮点数在转换为整型时,会将小数部分去掉,只保留整数部分。
var myFloat float32 = 3.1415926fmt.Println(int32(myFloat)) //3
6.1 修改字符串
Golang语言的字符串是不可变的
修改字符串时,可以将字符串转换为[]byte进行修改
[]byte和string可以通过强制类型转换
案例:将8080改为8081
var str1 string = "localhost:8080"fmt.Println(str1)str := []byte(str1)str[len(str1)-1] = '1'fmt.Println(string(str)) //localhost:8081
字符串替换, 比如将 "Hello, 码神之路Java教程" 替换为 "Hello, 码神之路Go教程"
思路:
- 找到Java所在的位置
- 根据Java的长度将其分为两部分
- 加上Go总共三部分,进行拼接
var str string = "Hello, 码神之路Java教程"sorce := "Java"target := "Go"index := strings.Index(str, sorce)headStr := str[:index]lastStr := str[index+len(sorce):]targetStr := headStr + target + lastStrfmt.Println(targetStr)