(Go语言)初上手Go?本篇文章帮拿捏Go的数据类型!
1. bool 类型
布尔类型:只有 true 和 false 两种值
在Go中,整数 0 不代表 false 值,1也不代表 true 值
- 即数字无法代替布尔值进行逻辑判断,两者是完全不同的类型
布尔类型占用 1 字节
2. int 整型
Go中为不同位数的整数分配了不同的类型,主要分为无符号整型与有符号整型。
序号 | 类型和描述 | 占用空间 | 表数范围 |
---|---|---|---|
uint8 | 无符号 8 位整型 | 1字节 | 0~255 |
uint16 | 无符号 16 位整型 | 2字节 | 0~216-1 |
uint32 | 无符号 32 位整型 | 4字节 | 0~232-1 |
uint64 | 无符号 64 位整型 | 8字节 | 0~264-1 |
int8 | 有符号 8 位整型 | 1字节 | -128~127 |
int16 | 有符号 16 位整型 | 2字节 | -215~215-1 |
int32 | 有符号 32 位整型 | 4字节 | -231~231-1 |
int64 | 有符号 64 位整型 | 8字节 | -263~263-1 |
uint | 无符号整型 至少32位 | ||
int | 整型 至少32位 | ||
uintptr | 等价于无符号64位整型,但是专用于存放指针运算,用于存放死的指针地址。 |
若出现溢出问题,Goland会帮你自动显示出来
还有两个数据类型
- rune 类型,有符号,与int32等价,等价于int32,表示一个Unicode码
- byte 类型,无符号,与uint8等价,当要存储字符时选用byte
- Go 各整数类型分:有符号和无符号,int uint 的大小和系统有关
- Go 的整型默认声明为int类型
- Go程序中 整型变量 在使用时,遵守保小不保大的原则,即:在保证程序正确运行的情况下,尽量是哟ing占用空间小的数据类型。【如:年龄可以使用uint8类型】
- bit:计算机中最小的存储单位,byte:计算机中基本的存储单元
var e = 11
// 如何查看某个变量所占用的字节数,可以使用unsafe包下的Sizeof()方法
fmt.Println(unsafe.Sizeof(e)) // 8 字节,Go默认使用的是int64也就是int类型
3. float 浮点型
IEEE-754
浮点数,主要分为单精度浮点数(float32)与双精度浮点数(float64)。
类型 | 类型和描述 | 存储空间 | 表数范围 |
---|---|---|---|
float32 | IEEE-754 32位浮点数 | 4字节 | -3.504E38~3.403E38 |
float64 | IEEE-754 64位浮点数 | 8字节 | -1.798E308~1.798E308 |
关于浮点数在机器中存放形式的简单说明
- 浮点数=符号位+指数位+尾数位
- 尾数部分可能丢失,造成精度损失
func main() {
var a float32 = -123.0000901 // -123.00009 精度缺失1位
var b float64 = -123.0000901 // -123.0000901
fmt.Println(a, b)
}
浮点型的一些小贴士:
- Go 浮点类型有固定范围和长度,不受具体OS的影响
- Go 浮点类型默认声明位 float64类型
- 浮点型常量有很多种表现形式,具体可以看一下浮点型字面量
- 通常情况下,也更推荐使用float64而不是float32,因为64比32的精度更高
4. complex 复数
类型 | 描述 | 存储范围 |
---|---|---|
complex128 | 64位实数和虚数 | 8字节 |
complex64 | 32位实数和虚数 | 4字节 |
var c complex64 = complex(1, 2) // 1+2i
var d complex128 = complex(1, 3) // 1+3i
fmt.Println(c, d)
fmt.Println(unsafe.Sizeof(c), unsafe.Sizeof(d))
Go提供了三个内建函数 complex、real 和 imag 来创建和操作复数
- complex(r, i float64) complex128
complex 函数用于创建一个复数。它接受两个参数,分别是复数的实部和虚部,并返回一个复数。
real 函数用于获取复数的实部。它接受一个复数作为参数,并返回该复数的实部。
imag 函数用于获取复数的虚部。它接受一个复数作为参数,并返回该复数的虚部。
5. char 字符
go语言字符串完全兼容UTF-8
类型 | 描述 |
---|---|
byte | 等价 uint8 可以表达ANSCII字符 |
rune | 等价 int32 可以表达Unicode字符 |
string | 字符串即字节序列,可以转换为[]byte 类型即字节切片 |
在 Go 中没有专门的字符类型(Java中是char类型),如果要存储耽搁字符(字母),一般使用byte类型来保存
字符串就是一串固定长度的字符链接起来的字符序列。
在传统字符串中,它们是由字符组合形成的字符串。而Go中,字符串的组成是由字节构成的
func main() {
var a byte = 'a'
var b int = '你'
var c string = "测试字符串"
fmt.Println(a, b, c)
}
如果字符在ASCII表的,例如[0-1,a-z,A-Z…]这种可以直接保存到byte类型
但如果字符对应的码值大于255,例如中文。这时就要使用int类型保存了
如果我们需要安装字符的方式输出,这时我们需要格式化输出可以使用…
fmt.Printf(“%c”,变量)
5.1 本质
- 在Go中,字符型默认都是使用UTF-8格式,在开发时就没有编码和乱码的困扰了
- 字符和码值的对应关系是通过字符编码表决定好的,也就是说所有字符本质都是数字码值,它们是可以参与数字运算的。
- 字符型 存储到 计算机中,需要将字符对应的码值(整数)找出来
- 存储:字符》对应码值》二进制》存储
- 读取:二进制》码值》字符》读取
6. string 字符串
字符串就是一串固定长度的字符连接起来的字符序列,Go的字符串是由单个字节连接起来的。
Go语言的字符串的字节使用UTF-8编码表示Unicode文本
var d = `test another useType`
fmt.Println(d)
使用细节
-
Go 语言的字符串的字节使用UTF-8编码标识Unicode文本,这样Golang统一使用UTF-8编码,中文乱码问题也就不存在了
-
字符串一旦赋值了,就不能再更改了;在Go中,字符串是不可变的。
为什么go语言中不能通过下标的方式进行修改?
- 因为go中的字符串的数据结构体是由一个指针和长度组成的结构体,该指针指向的一个切片才是真正的字符串值。
- go中源码字符串的底层结构:
type stringStruct struct { str unsafe.Pointer // 指向一个[]byte类型的切片指针 len int // 字符串的长度 }
因为底层是一个[]byte类型切片,使用下标的方式去修改值,这时候将一个字符内容赋给byte类型,是不允许的。对字符串重新赋值是可以的
因为go的底层其实是新创建了一个[]byte{}类型的切片,将变量str中的指针指向了新的内存空间地址(hello go)。原来的str存储的值(hello world)内存空间会随着垃圾回收机制被回收掉。
var e string = "不可变!"
e = "可变!" // 重新赋值是可以的
//e[0] = "可变吗?" // 不可以更改字符串
fmt.Println(e)
6.1 字面量
在Go中,字符串本质上是一个不可变的只读的字节数组,也是一片连续的内存空间。
字符串有两种字面量表达方式,分为普通字符串和原生字符串。
6.1.1 普通字符串
普通字符串由""
双引号表示,支持转义,不支持多行书写,下列是一些普通字符串
var a string = "like this!"
6.1.2 原生字符串
原生字符串由反引号表示,不支持转义,支持多行书写,原生字符串里面所有的字符都会原封不动的输出,包括换行和缩进。
`这是一个原生字符串....
它是支持换行的
在原生字符串中 \t 换行和 \t 缩进 无效
`
6.2 访问
因为字符串本质是字节数组,所以字符串的访问形式跟数组切片完全一致,例如访问字符串第一个元素
str := "this is a string,please check me"
fmt.Println(str[0], len(str)) // 索引下标处的元素是字符的字节,本质是切片所以可以使用len方法
因为本质是切片,所以对于字符串的截取会更加的简单,直接使用切片表达式即可
// 切割字符串
s := string(str[5:16])
fmt.Println(s) // is a string
尽管字符串本质是一个切片数组,但是你不可以由下标来更改字符串中的字符
不过,你可以直接赋值,重新赋值一个新字符串
//str[0] = 's' // 无法通过编译
//str[0] = "s" // 无法通过编译
str = "this is a new string"
fmt.Println(str)
6.3 转换
字符串可以转换为字节切片,而字节切片或字节数组也可以转换为字符串
str := "this is a string"
// 显式类型转换为字节切片
bytes := []byte(str)
fmt.Println(bytes)
// 显式类型转换为字符串
fmt.Println(string(bytes))
虽然字符串中的字符不能够修改,但是切片是可以进行更改的。
所以只需要把字符串转为切片,那么就可以对切片进行更改了。
添加的字符必须是ASCII码,Go是按照ASCII码来比辨认字符的
str := "this is a string"
fmt.Println(&str)
bytes := []byte(str)
// 修改字节切片
bytes = append(bytes, 97, 98, 99)
// 赋值给原字符串
str = string(bytes)
fmt.Println(str) // this is a stringabc
将字符串转换成字节切片以后,两者之间毫无关联,因为Go会新分配一片内存空间给字节切片,再将字符串的内存复制过去,对字节切片进行修改不会对原字符串产生任何影响,这么做是为了内存安全。
6.4 拼接
字符串拼接可以使用+
操作符,也可以转换为切片再使用append()
方法添加元素
func main() {
str := "this is a string"
str = str + " that is a int"
fmt.Println(str)
str1 := "this is a string"
bytes := []byte(str1)
bytes = append(bytes, "that is a int"...)
str1 = string(bytes)
fmt.Println(str1)
}
不过这两种拼接的性能都很差,如果对性能有更高的要求,建议使用strings.Builder()
// 创建一个字符串构造器
builder := strings.Builder{}
// WriteString方法:在字符串构造器的末尾添加指定字符串
builder.WriteString("this is a string ")
builder.WriteString("that is a int")
fmt.Println(builder.String())
6.5 遍历
Go 中的字符串是一个只读的字节切片,也就是说字符串的组成单位是字节而不是字符。
因此,我们也可以对字符串进行遍历操作
func main() {
str := "hello world!"
for i := 0; i < len(str); i++ {
fmt.Printf("%d,%x,%s\n", str[i], str[i], string(str[i]))
}
}
7. 默认值(零值)
官方文档中零值称为zero value
,零值并不仅仅只是字面上的数字零,而是一个类型的空值或者说默认值更为准确。
类型 | 零值 |
---|---|
数字类型 | 0 |
布尔类型 | false |
字符串类型 | "" |
数组 | 固定长度的对应类型的零值集合 |
结构体 | 内部字段都是零值的结构体 |
切片,映射表,函数,接口,通道,指针 | nil |
8. nil
源代码中的nil
,可以看出nil
仅仅只是一个变量。
var nil Type
Go中的nil
并不等同于其他语言的null
,nil
仅仅只是一些类型的零值,并且不属于任何类型,而nil == nil
会返回true
var nil string
println("nil值:", nil) // nil值:
9. 派生类型
类型 | 例子 |
---|---|
数组 | [5]int ,长度为5的整型数组 |
切片 | []float64 ,64位浮点数切片 |
映射表 | map[string]int ,键为字符串类型,值为整型的映射表 |
结构体 | type Gopher struct{} ,Gopher结构体 |
指针 | *int ,一个整型指针。 |
函数 | type f func() ,一个没有参数,没有返回值的函数类型 |
接口 | type Gopher interface{} ,Gopher接口 |
通道 | chan int ,整型通道 |
10. 😍前篇知识回顾
- Go的环境安装与开发工具配置
- Go的运行流程步骤与包的概念
- (Go)变量与常量?字面量与变量的较量!
11. 💕👉 其他好文推荐
- 还不了解Git分布式版本控制器?本文将带你全面了解并掌握
- 带你认识Maven的依赖、继承和聚合都是什么!有什么用?
- 2-3树思想与红黑树的实现与基本原理
- !全网最全! ElasticSearch8.7 搭配 SpringDataElasticSearch5.1 的使用
- 全面深入Java GC!!带你完全了解 GC垃圾回收机制!!
- 全面了解Java的内存模型(JMM)!详细清晰!
- 在JVM中,类是如何被加载的呢?本篇文章就带你认识类加载的一套流程!
全文资料学习全部参考于:Golang中文学习文档