1.1 分类
""
int和uint(有符号整数 / 无符号整数):根据底层平台,表示32位或者65位整数。除非使用非常大的整数,否则通常使用int来表示整数。
1.1.1 类型应用
// 布尔类型
var b bool = false
// 整型
var i int = 10
// 浮点型
var f float = 3.14
f2 := 12.0
1.1.2 字符串型
""
//1. 定义字符串
var s1 string
s1 = "张三"
fmt.Printf("%T,%s\n", s1, s1)
s2 := `hello world`
fmt.Printf("%T,%s\n", s2, s2)
区别
package main
import "fmt"
func main(){
//2. 区别'A', "A"
v1 := 'A'
v2 := "A"
fmt.Printf("%T, %d\n", v1, v1)
fmt.Printf("%T, %s\n", v2, v2)
v3 := '中'
fmt.Printf("%T, %d, %c, %q\n", v3, v3, v3, v3)
}
控制台输出:
$ go run xxx.go
int32, 65
string, A
int32, 20013, 中, '中'
1.1.3 数据类型转换
Type(Value)T(V)
注意点:兼容类型可以互相转换
package main
import "fmt"
func main(){
var a int8
a = 10
var b int16
b = int16(a)
fmt.Println("a = ", a)
fmt.Println("b = ", b)
f1 := 4.83
var c int
c = int(f1)
fmt.Println("c = ", c)
}
控制台输出:
$ go run xxx.go
a = 10
b = 10
c = 4
2 复合数据类型
包括:
- 指针类型(Pointer)
- 数组类型
- 结构化类型(struct)
- Channel 类型
- 函数类型
- 切片类型
- 接口类型(interface)
- Map 类型
2.1 数组(Array)
Go语言提供了数组类型的数据结构。
数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。
数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素索引为0。
数组一旦定义后,大小不能更改。
2.1.1 数组的语法
声明和初始化数组
需要知名数组的大小和存储的数据类型。
variable_name [SIZE] variable_type
示例代码:
package main
import "fmt"
func main() {
//1. 创建数组
var arr1 [5]int
arr1[0] = 1
arr1[1] = 2
arr1[2] = 3
arr1[3] = 4
arr1[4] = 5
fmt.Println("arr1的长度是:", len(arr1))
fmt.Println("arr1的容量是:", cap(arr1))
}
结果输出:
$ go run xxx.go
arr1的长度是: 5
arr1的容量是: 5
数组其他创建方式:
var a [10]float32
fmt.Println(a)
var b = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
fmt.Println(b)
var c = [5]int{1, 2, 4}
fmt.Println(c)
var d = [5]int{1:1, 3:2}
fmt.Println(d)
var e = []int{6, 7, 8, 9, 10}
fmt.Println(e)
结果输出:
$ go run xxx.go
[0 0 0 0 0]
[1000 2 3.4 7 50]
[1 2 4 0 0]
[0 1 0 2 0]
[6 7 8 9 10]
2.1.2 数组拷贝是值传递,深拷贝
var e = [5]int{6, 7, 8, 9, 10}
fmt.Println("e = ", e)
var f [5]int
f = e // 值传递
f[1] = 1
fmt.Println("e = ", e)
fmt.Println("f = ", f)
fmt.Println("f == e ? ", e == f)
var d = [5]int{1:1, 3:2}
fmt.Println("d = ", d)
g := d // 值传递
g[1] = 2
fmt.Println("d = ", d)
fmt.Println("g = ", g)
fmt.Println("g == d ? ", d == g)
结果输出:
e = [6 7 8 9 10]
e = [6 7 8 9 10]
f = [6 1 8 9 10]
f == e ? false
d = [0 1 0 2 0]
d = [0 1 0 2 0]
g = [0 2 0 2 0]
g == d ? false
2.1.3 多维数组
2.2 切片(slice)
2.2.1 什么是切片
Go语言切片是对数组的抽象。
"动态数组"
[]
三个元素
- 指针,指向数组中slice指定的开始位置
- 长度,即slice的长度
- 最大长度,也就是slice开始位置到数组最后位置的长度
package main
import "fmt"
func main() {
/*
数组array:
存储一组相同数据类型的数据结构
特点:定长
切片slice:
同数组类似,也叫做变长数组或者动态数组
特点:变长
是一个引用类型的容器,指向了一个底层数组
makde()
func make(t Type,size ... IntegerType) Type
第一个参数:类型
slice,map,chan
第二个参数:长度len
实际存储元素的数量
第三个参数:容量cap
最多能够存储的元素的数量
*/
//1. 数组
arr := [4]int{1,2,3,4}
fmt.Println(arr)
//2. 切片
var s1 []int
fmt.Println(s1)
s2 := []int{1,2,3,4}
fmt.Println(s2)
fmt.Printf("arr type is %T,s2 type is %T\n", arr, s2)
s3 := make([]int, 3, 8)
fmt.Println(s3)
fmt.Printf("s3 容量:%d, 长度: %d\n", cap(s3), len(s3))
}
结果输出:
[1 2 3 4]
[]
[1 2 3 4]
arr type is [4]int,s2 type is []int
[0 0 0]
s3 容量:8, 长度: 3
2.2.2 append
两种方法:
slice = append(slice, elem1, elem2)
slice = append(slice, anotherslice...)
实例:
package main
import "fmt"
func main() {
s3 := make([]int, 3, 8)
fmt.Println(s3)
fmt.Printf("s3 容量:%d, 长度: %d\n", cap(s3), len(s3))
s3[0] = 1
s3[1] = 2
s3[2] = 3
fmt.Println(s3)
//fmt.Println(s3[3]) runtime error: index out of range [3] with length 3
//append elem
s4 := make([]int, 0, 5)
fmt.Println(s4)
s4 = append(s4, 1, 2)
fmt.Println(s4)
s4 = append(s4, 3, 4, 5, 6) // 添加超过最大cap的数量
fmt.Println(s4)
//append anotherslice
s4 = append(s4, s3...)
fmt.Println(s4)
}
结果输出:
[0 0 0]
s3 容量:8, 长度: 3
[1 2 3]
[]
[1 2]
[1 2 3 4 5 6]
[1 2 3 4 5 6 1 2 3]
2.2.3 slice自动扩容
/*
切片slice:
1. 每一个切片引用了一个底层数组
2. 切片本身不存在任何数据,都是这个底层数组存储,所以修改切片也就是修改这个数组中的数据
3. 当向切片中添加数据时,如果没有超过容量,直接添加,如果超过容量,自动扩容(原容量 × 2)
4. 切片一旦扩容,就是重新指向了一个新的底层数组
*/
s1 := []int{1, 2, 3}
fmt.Println(s1)
fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:3,cap:3
fmt.Printf("%p\n", s1)
s1 = append(s1, 4, 5)
fmt.Println(s1)
fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:5,cap:6
fmt.Printf("%p\n", s1)
s1 = append(s1, 6, 7, 8)
fmt.Println(s1)
fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:8,cap:12
fmt.Printf("%p\n", s1)
结果输出:
[1 2 3]
len:3,cap:3
0xc0000b6000
[1 2 3 4 5]
len:5,cap:6
0xc0000aa030
[1 2 3 4 5 6 7 8]
len:8,cap:12
0xc00008c060
2.2.4 数组切片初始化
s :=[] int {1,2,3 }
[]cap=len=3
s := arr[:]
初始化切片 s,是数组 arr 的引用。
s := arr[startIndex:endIndex]
startIndexendIndex-1
s := arr[startIndex:]
默认 endIndex 时将表示一直到arr的最后一个元素。
s := arr[:endIndex]
默认 startIndex 时将表示从 arr 的第一个元素开始。
s1 := s[startIndex:endIndex]
切片 s
s :=make([]int,len,cap)
make()[]int
2.3 Map
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
2.3.1 定义 Map
可以使用内建函数 make 也可以使用 map 关键字来定义 Map:
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
示例:
package main
import "fmt"
func main() {
var map1 map[string]int //没有初始化
var map2 = make(map[string]int) //创建
map2["xiaoming"] = 1
var map3 = map[string]int{"Go":98, "Python":87, "Java":79, "Html":93}
fmt.Println(map1)
fmt.Println(map2)
fmt.Println(map3)
fmt.Println(map1 == nil)
fmt.Println(map2 == nil)
fmt.Println(map3 == nil)
if map1 == nil {
map1 = make(map[string]int)
fmt.Println(map1)
}
}
输出:
map[]
map[xiaoming:1]
map[Go:98 Html:93 Java:79 Python:87]
true
false
false
map[]
2.3.2 Map的使用
package main
import "fmt"
func main() {
//创建
var map1 = make(map[string]int)
//修改数据
map1["xiaoming"] = 18
map1["xiaohong"] = 17
map1["xiaolan"] = 16
fmt.Println(map1)
//删除数据delete
delete(map1,"xiaoming")
fmt.Println(map1)
//长度
fmt.Println(len(map1))
}
结果输出:
map[xiaohong:17 xiaolan:16 xiaoming:18]
map[xiaohong:17 xiaolan:16]
2
2.3.3 Map的遍历
var map1 map[string]int /*创建集合 */
map1 = make(map[string]int)
/* map插入key - value对,各个国家对应的首都 */
map1 [ "France" ] = 1
map1 [ "Italy" ] = 2
map1 [ "Japan" ] = 3
map1 [ "India " ] = 4
/*使用键输出地图值 */
for k, v := range map1 {
fmt.Println(k, "---->", v)
}
for k := range map1 {
fmt.Println(k, "---->", map1[k])
}
结果输出:
France ----> 1
Italy ----> 2
Japan ----> 3
India ----> 4
India ----> 4
France ----> 1
Italy ----> 2
Japan ----> 3
2.3.4 判断key是否存在
判断American是否存在
package main
import "fmt"
func main() {
var map1 map[string]int /*创建集合 */
map1 = make(map[string]int)
/* map插入key - value对,各个国家对应的首都 */
map1 [ "France" ] = 1
map1 [ "Italy" ] = 2
map1 [ "Japan" ] = 3
map1 [ "India " ] = 4
/*查看元素在集合中是否存在 */
capital, ok := map1 [ "American" ] /*如果确定是真实的,则存在,否则不存在 */
/*fmt.Println(capital) */
/*fmt.Println(ok) */
if (ok) {
fmt.Println("American :", capital)
} else {
fmt.Println("American 不存在")
}
}
结果输出:
American 不存在
2.3.5 map结合slice使用
用例:将map中的信息统一打印
package main
import "fmt"
func main() {
//第一个人
map1 := make(map[string]string)
map1["name"] = "王二狗"
map1["age"] = "30"
map1["sex"] = "男性"
map1["address"] = "北京市XX路XX号"
//第二个人
map2 := make(map[string]string)
map2["name"] = "李小花"
map2["age"] = "20"
map2["sex"] = "女性"
map2["address"] = "上海市XX路XX号"
//第三个人
map3 := map[string]string{"name":"ruby","age":"30","sex":"女性","address":"杭州市"}
//将map存到slice中
s1 := make([]map[string]string, 0, 3)
s1 = append(s1, map1)
s1 = append(s1, map2)
s1 = append(s1, map3)
//便利切片
for i, val := range s1 {
//val: map1, map2, map3
fmt.Printf("第%d个人的信息是:\n", i)
fmt.Printf("\t姓名:%s\n", val["name"])
fmt.Printf("\t年龄:%s\n", val["age"])
fmt.Printf("\t性别:%s\n", val["sex"])
fmt.Printf("\t地址:%s\n", val["address"])
}
}
结果输出:
第0个人的信息是:
姓名:王二狗
年龄:30
性别:男性
地址:北京市XX路XX号
第1个人的信息是:
姓名:李小花
年龄:20
性别:女性
地址:上海市XX路XX号
第2个人的信息是:
姓名:ruby
年龄:30
性别:女性
地址:杭州市