Golang 基础 - 数据类型
基本数据类型
类型 | 关键字 |
---|---|
整型 | int (byte int8 ) int16 (rune int32 ) int64 uint uint8 uint16 uint32 uint |
浮点型 | float32 (精度7位) float64 (精度16位) |
字符型 | rune |
错误 | error |
字符串 | string |
布尔型 | bool |
fmt.Printf 的一些常用占位符
占位符 | 作用 |
---|---|
%T | 取类型 |
%d | 十进制数 |
%b | 二进制数 |
%s | 字符串 |
%t | 布尔值 |
%p | 内存地址 |
%f | 浮点数 |
%e | 科学计数法 |
整型、浮点型
除了 byte 表示 int8 、rune 表示 int32 以及 ++ 和 – 只能单独存在外,其它的不用多说了,上示例:
import (
"fmt"
)
func main() {
var num_byte byte = 1
var num_int8 int8 = 1
var num_rune rune = 1
var num_int32 int32 = 1
// num_byte = int8, num_int8 = int8, num_rune = int32, num_int32 = int32
fmt.Printf("num_byte = %T, num_int8 = %T, num_rune = %T, num_int32 = %T\n", num_byte, num_int8, num_rune, num_int32)
// Golang 有加(+)减(-)乘(*)除(/)取余(%)自加(++)自减(--) 7 种算数运行符
var numA int32 = 2
numA++ // Golang 中 ++numA 为错误语法
fmt.Println(numA) // 3
numA-- // Golang 中 --numA 为错误语法
fmt.Println(numA) // 2
}
字符串、字符
Golang 的字符串是不可变的,上示例:
import (
"fmt"
)
func main() {
// Go 语言的字符串使用双引号("")或者反引号(``)
str := "ABCDE"
// str = (string, ABCDE)
fmt.Printf("str = (%T, %s)\n", str, str)
strA := "A"
charA := 'A'
// Golang 的字符类型(rune)就是32位整型(int32)
// strA = (string, A), charA = (int32, A)
fmt.Printf("strA = (%T, %s), charA = (%T, %c)\n", strA, strA, charA, charA)
// Golang 的语言使用 UFT-8 编码,中文占 3 个字节
zhStr := "你好,世界"
// 因为中文占 3 个字节,所以使用 len 方法将输出 13
// zhStr = (string, 13)
fmt.Printf("zhStr = (%T, %d)\n", zhStr, len(zhStr))
// 使用 unicode/utf8 包提供的 RuneCountInString 方法获取字符的数目
// zhStr = (string, 5)
fmt.Printf("zhStr = (%T, %d)\n", zhStr, utf8.RuneCountInString(zhStr))
// 或者使用 rune 类型处理(数据类型的转换)
// zhStr = (string, 5)
fmt.Printf("zhStr = (%T, %d)\n", zhStr, len([]rune(zhStr)))
}
布尔型
布尔型只有 true
和 false
和其它语言一样都有一些关系运算符,上示例:
import (
"fmt"
)
func main() {
fmt.Println(true && true, true)
fmt.Println(true && false, false)
fmt.Println(false && true, false)
fmt.Println(false && false, false)
fmt.Println(true || true, true)
fmt.Println(true || false, true)
fmt.Println(false || true, true)
fmt.Println(false || false, false)
fmt.Println(!true, false)
fmt.Println(!false, true)
}
错误
错误 (error
) 是 Golang 的内置类型本质上是一个接口
type error interface {
Error() string
}
示例:
import (
"fmt",
"errors"
)
func main() {
fmt.Println(errors.New("Hello Error")) // Hello Error
}
复合数据类型
类型 | 说明 |
---|---|
array | 数组 |
slice | 切片 |
map | 字典 |
function | 函数 |
interface | 接口 |
channel | 通道 |
pointer | 指针 |
数组
Golang 的数组的声明和其它语言不太一样,中括号[]
既不是写在变量名的后面,也不是写在类型的后面,而是写在类型的前面,语法为
var 变量名 [长度]数据类型
示例:
import (
"fmt"
)
func main() {
// 声明一个长度为 5 的数组
var arrayA [5]int
// 数组会使用默认值进行填充,使用索引进行访问和修改
arrayA[3] = 1
// 也可以在声明时一同进行初始化
arrayB := [5]int{1,2,3} // 1,2,3,0,0
// 或者使用指定索引
arrayC := [5]int{1:1,3:2} // 0,1,0,2,0
// 使用 ...代替长度会自动填充长度
arrayD := [...]int{1,2,3,4} // 长度为4
arrayE := [...]int{2:1,6:2} // 长度为 7
}
遍历数组:
import (
"fmt"
)
func main() {
array := [...]int{1,2,3,4,5}
// 使用 fori 循环遍历
for i := 0; i < len(array); i++ {
fmt.Printf("array[%d] = %d\n", i, array[i])
}
for index, value := range array {
fmt.Printf("array[%d] = %d\n", index, value)
}
}
多维数组和其它语言类似
import (
"fmt"
)
func main() {
array := [][]int{{1,2,3},{4,5,6},{7,8,9}}
for _, arr := range array {
for _, value := range arr {
fmt.Printf("%d ", value)
}
fmt.Println()
}
}
切片
Golang 的数组和大部分的编程语言类型,都是在声明大小后就不能够再对大小进行改变,所以就有了切片slice
的出现,切片的声明和数组类似,不过不需要指定长度:
var 切片名 []数据类型
切片有两个重要属性值,一个是长度使用
len
方法,一个是容量使用cap
方法通过使用
make
方法可以对这两个值进行初始化
make([]数据类型, 长度[,容量])
容量可以不传,默认和长度一样大
使用内置的append
方法在切片的末尾追加元素
append 方法当容量足够时,不会创建一个新的地址,而当容量不够时则会创建一个新的地址,且新的切片容量为之前的两倍,前提都是左右两边操作的切片都相同,即
slice = append(slice, [元素]...)
import (
"fmt"
)
func main() {
var slice1 []int
var slice2 []int
slice2 = append(slice1, 1, 2, 3)
fmt.Println(slice1) // []
fmt.Println(slice2) // [1,2,3]
}
Golang 没有提供具体的删除切片元素的方法,一般通过使用获取切片片段来代替删除,示例
func main() {
slice := []int{1,2,3,4}
slice = slice[:] // slice = [1,2,3,4]
slice = slice[1:] // slice = [2,3,4]
slice = slice[:2] // slice = [2,3]
// slice 的地址会发生改变
}
字典(map)
Golang 的 map 是无序的,不能通过下标获取,只能通过 key 访问对应的值
import (
"fmt"
)
func main() {
var map1 map[string]int // 声明一个key类型为字符串,value类型为int的map,没有初始化化,map1 为 nil
map2 := make(map[string]int) // 声明并创建一个key类型为字符串,value类型为int的map,没有初始化化,map2 不为 nil
map3 := map[string]int{"WenFlower": 99, "Wen": 60, "Flower": 59} // 声明并初始化map
fmt.Println(map1 == nil) // true
// 存储键值对到 map
map2["WenFlower"] = 99
// 获取key对应的value
fmt.Println(map3["WenFlower"]) // 99
// 获取 key 对应的值,以及是否存在对应的值 ok 为 true 表示存在,false 表示不存在
value, ok := map3["WenFlower"]
fmt.Println(value, ok) // 99, true
// 删除对应的key
delete(map3, "WenFlower")
value, ok = map3["WenFlower"]
fmt.Println(value, ok) // 0, false
// 获取 map 的长度
fmt.Println(len(map3)) // 2
// 遍历 map
for key, val := range map3 {
fmt.Printf("map[%s] = %d\n", key, val)
}
}
sync.Map
Golang 在 1.9 后提供的一个线程安全的键值对结构,但是使用几乎和 map 数据类型毫不相干
import (
"fmt"
"sync"
)
func main() {
// 声明 sync.Map 就能直接使用
var syncMap sync.Map
// 存储key
syncMap.Store("WenFlower", 99)
syncMap.Store("Wen", 60)
syncMap.Store("Flower", 59)
// 获取 key 值
fmt.Println(syncMap.Load("WenFlower")) // 99 true
fmt.Println(syncMap.Load("WenFlower11")) // nil false
// 删除 key 值
syncMap.Delete("WenFlower")
syncMap.Delete("WenFlower1111") // 删除不存在的 key 不会出现错误
// 遍历
syncMap.Range(func(key, value interface{}) bool {
fmt.Printf("map[%s] = %d\n", key, value)
return true
})
}