数据类型
Go 是一种强类型语言。
每个变量都绑定到特定的数据类型,并且只接受与此类型匹配的值。
数据类型
| 类型 |
|
| 基本类型 |
数字、字符串和布尔值 |
| 聚合类型 |
数组和结构 |
| 引用类型 |
指针、切片、哈希、函数和管道 |
| 接口类型 |
接口 |
数值类型
基本类型
| 类型 |
说明(位是bit) |
| int |
有符号整数,为32位或64位,由编译器决定 |
| uint |
无符号整数,为32位或64位,由编译器决定 |
| int8 |
8位有符号整数 |
| int16 |
16位有符号整数 |
| int32 |
32位有符号整数 |
| int64 |
64位有符号整数 |
| uint8 |
8位无符号整数 |
| uint16 |
16位无符号整数 |
| uint32 |
32位无符号整数 |
| uint64 |
64位无符号整数 |
| rune |
int32 数据类型的别名。 它用于表示 Unicode 字符(或 Unicode 码位) |
| uintptr |
无符号int指针类型 |
| float32 |
浮点数 |
| float64 |
浮点数 |
| complex128 |
复数 |
| complex64 |
复数 |
| bool |
布尔类型 |
| byte |
字节类型,同uint8 |
| string |
字符串类型 |
| error |
错误类型 |
bool类型
布尔类型值为true和false
不支持自动或者强制类型转换
类型转换
不同类型之间不支持运算
显式声明类型转换
| Go |
|---|
| var test int32 = 1
var test2 uint32 = (uint32)test
|
类型声明
type new_type old_type
new_type和old_type 底层相同,但仍是不同的类型
字符类型
byte: 代表UTF8字符串的单个字节的值
rune: 代表unicode字符
指针
指针的值是一个变量的地址
变量生命周期
| Go |
|---|
1
2
3
4
5
6
7
8
9
10
11
12 | var p *int
fun f() {
var x int = 1
p = &x
}
//由于p指向局部变量x,x将从堆申请内存
fun g() {
y := new(int)
*y = 1
}
//由于y指向的地址只在函数内使用,当函数结束时,该内存将被自动释放
|
字符串
字符串是不可变的字节序列,初始化后不能被修改
文本字符串被解读成安UTF-8编码的Unicode字符
每个元素为uint8类型
| Go |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13 | package main
import "fmt"
func main() {
test := "123"
test1 := "测试"
fmt.Println(len(test), len(test1))
test2 := test[:1] //创建新的字符串
test3 := test + test1 //字符串拼接,产生新的字符串
}
//每个汉字占3个字节
//输出: 3 6
|
扩容
定义新的字符串
遍历
| Go |
|---|
1
2
3
4
5
6
7
8
9
10
11
12 | var str = "it is test"
//根据长度遍历
strLen := len(str)
for i:=0; i<strLen; i++ {
fmt.PrintLn(str[i])
}
//range
for i,v := range str { //注意range返回值为int32类型
fmt.PrintLn(i,v)
}
|
处理包
- bytes
- strings
- strconv
- unicode
数组
数组是一种特定类型且长度固定的数据结构
- 可以有零个或多个元素
- 必须在声明或初始化时指定大小
- 无法动态调整大小
- 通过下标访问,从0开始到len-1
- 根据类型默认初始化,或者指定赋值
鉴于这些原因,数组在 Go 程序中并不常用,但它们是切片和映射的基础。
声明
| Go |
|---|
| //int类型数组,该数组有3个元素
var a [3]int
//string类型数组,该数组有3个元素
var b [3]string
//初始化多维数组
var twoD [3][5]int
|
初始化
| Go |
|---|
1
2
3
4
5
6
7
8
9
10
11
12 | //申请全局变量
var cities [5]string = [5]string{"New York", "Paris", "Berlin", "Madrid"}
//函数内局部变量
cities := [5]string{"New York", "Paris", "Berlin", "Madrid"}
//如果不知道需要多少个位置,但知道具有多少数据,那么使用省略号 (...),如下例所示:
q := [...]int{1, 2, 3}
//注意:=只能在函数内使用
//特定位置赋初值
numbers := [...]int{99: -1}
|
值类型
数组是值类型,在赋值或作为参数传递时,将被复制
切片
var name []Type
切片只是基础数组的一个视图
切片的大小是动态的,不是固定的
属性
- 指针,指向原生数组的指针
- 长度,切片内元素的个数。使用len()计算当前切片长度
- 容量,切片存储空间大小。使用cap()计算容量。
- 无法动态扩容,只能创建新切片(append时会自动扩容)
空切片
通过len判断数组是否为空
| Go |
|---|
| var s []int //len(s)==0 s==nil
s = nil //len(s)==0 s==nil
s = []int(nil) //len(s)==0 s==nil
s = []int{} //len(s)==0 s!=nil
|
创建
- 基于数组创建切片
- 基于切片创建切片
- 使用make()创建
| Go |
|---|
| //该切片的长度len和cap均为0
var slice0 []string
//基于数组创建切片 len:2 cap:12
months := [...]string{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
slice1 := months[0:1]
//使用make创建切片,len:10
slice2 := make([]string, 10, 100) cap:100
|
访问
切片运算符 s[i]
追加元素
内置函数 slice = append(slice, element)向切片添加元素
当切片长度不够时,会自动分配新的切片
删除
无内置删除函数
通过创建新切片删除
| Go |
|---|
| letters := []string{"A", "B", "C", "D", "E"}
remove := 2
letters = append(letters[:remove], letters[remove+1:]...)
|
切片拷贝
copy(dst, src []Type)
map
哈希表
格式
初始化
| Go |
|---|
1
2
3
4
5
6
7
8
9
10
11
12 | studentsAge := map[string]int{
"john": 32,
"bob": 31,
}
t := map[int]int{} //创建空map
var studentsAge = make(map[string]int)
//注意
var studentsAge map[string]int
//该方式定了一个nil,不能直接访问
|
添加
| Go |
|---|
| studentsAge := make(map[string]int) //正确定义
射,后续赋值将出错
studentsAge["john"] = 32
studentsAge["bob"] = 31
fmt.Println(studentsAge)
|
查找
| Go |
|---|
| value, ok := map_test["123"]
if ok {
do something...
}
|
访问项
下标表示法 map[key]
| Go |
|---|
| studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
fmt.Println("Bob's age is", studentsAge["bob"])
}
|
遍历
| Go |
|---|
| studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
for name, age := range studentsAge {
fmt.Printf("%s\t%d\n", name, age)
}
|
删除
内置函数delete()删除
| Go |
|---|
| studentsAge := make(map[string]int)
studentsAge["john"] = 32
studentsAge["bob"] = 31
delete(studentsAge, "john")
fmt.Println(studentsAge)
}
|
结构体
结构体可包含零个或多个任意类型的字段,并将它们表示为单个实体。
声明和初始化
使用 struct 关键字声明结构
| Go |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | // 例如,若要定义员工结构
type Employee struct {
ID int
FirstName string
LastName string
Address string
}
//然使用新类型声明一个变量
var john Employee
//声明变量的同时对其进行初始化
employee := Employee{1001, "John", "Doe", "Doe's Street"}
//指定字段赋值
employee := Employee{LastName: "Doe", FirstName: "John"}
//通过.访问
employee.ID = 1001
fmt.Println(employee.FirstName)
|
成员定义
通常将结构体成员首字母大写
便于夸包引用
结构嵌入
通过 Go 中的结构,可将某结构嵌入到另一结构中
| Go |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | //一种针对员工,一种针对合同工
//你可具有一个包含公共字段的 Person 结构,如下例所示:
//公共字段
type Person struct {
ID int
FirstName string
LastName string
Address string
}
//Employee
type Employee struct {
Information Person
ManagerID int
}
|
匿名嵌套
定义只包含类型,不带名称的结构体成员
| Go |
|---|
| type Person struct {
ID int
FirstName string
LastName string
Address string
}
//Contractor
type Employee struct {
Person //匿名嵌套
ManagerID int
}
|
| Go |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | package main
import "fmt"
type Person struct {
ID int
FirstName string
LastName string
Address string
}
type Employee struct {
Person
ManagerID int
}
type Contractor struct {
Person
CompanyID int
}
func main() {
employee := Employee{
Person: Person{
FirstName: "John",
},
}
employee.LastName = "Doe"
fmt.Println(employee.FirstName)
}
|