Go对应的复合数据类型有数组,字典,指针,切片,通道,结构和结构,他们字面类型如下:
[n] elementType //数组
map [keyType]valueType //字典
* pointerType //指针
[] elementType //切片
chan valueType //通道
struct {
fieldType fieldType
}
interface {
method1(inputParams)(returnParams)
}
• 指针
var a = 11
p := &a
type User struct{
name string
age int
}
andes := User{
name: "andes",
age: 18,
}
p := &andes
fmt.Println(p.name)
// Go不支持指针运算
a := 1234
p := &a
p++ //不允许,error
//函数中允许返回局部变量地址
func sum (a, b int) *int {
sum := a + b
return &sum //允许,sum会被分配在heap上
}
• 数组
• 数组初始化
var arr [2]int //声明
array := [...]float64{7.0, 8.0}
a := [3]int{1, 2, 3} //指定长度初始化
b := [...]int{4, 5, 7} //不指定长度初始化
c := [3]int{1:1, 2:3} //指定长度,通过索引值初始化
d := [...]int{1:1, 2:3} //不指定长度,通过索引值初始化
• 数组特点
• 数组长度一旦创建就固定了,不可以追加元素
• 数组是值类型,数组赋值或者作为函数参数都是值拷贝
a1 := [3]int{1, 2, 3}
a2 := a1
a2[0] = 11 //这里拷贝了一份
fmt.Println(a1) //[1, 2, 3]
fmt.Println(a2) // [11, 2, 3]
• 数组长度是数组类型的组成部分,[10]int和[20]int表示不同类型
• 可以根据数组创建切片
• 数组长度: len(array)
• 数组遍历
a := [...]int{1, 2, 3}
b := a[0]
// 类似python遍历
for i,v := range a {
fmt.Printlb(i)
}
alength := len(a)
for i:=0, i<alength; i++ {
}
• 切片
因为Go的数组的长度定长和值拷贝限制了使用场景,Go提供了slice,这是一种可变数组
// src/runtime/slice.go
type slice struct {
array unsafe.Pointer
len int
cap int
}
• 切片的创建
• 根据数组创建
// 创建语法array[a:b] 左边包含,右边不包含
var array = [...]int{1, 2, 3}
s1 := array[0:4]
• 根据内置函数make创建切片
// len=10, cap=10
a := make([]int, 10)
// len=10, cap=15
a := make([]int, 10, 15)
• 切片的操作
• len()返回长度
• cap()返回容量
• append()追加元素
• copy()复制一个切片
a := [...]int{0, 1, 2, 3, 4}
b := make([]int, 2, 4)
c := a[0:3]
fmt.Println(len(b)) //2
fmt.Println(cap(b)) //4
b = append(b, 1)
fmt.Println(b) // [0, 0, 1]
fmt.Println(b) // 3
b = append(b, c)
fmt.Println(b) //[0, 0, 1, 0, 1, 2]
fmt.Println(len(b)) //6
fmt.Println(cap(b)) // 8, 底层数组发生自动扩展
d := make([]int, 2, 2)
copy(d, c) //复制d和c长度最小的
fmt.Println(d) // [0, 1]
fmt.Println(len(d)) // 2
fmt.Println(cap(d)) // 2
• map
map[K]T,K必须是任意可以比较的类型,T是值类型,map是一种引用类型
• 创建Map
• 直接创建
dict := map[string]string{"a": "a1", "b": "b1"}
fmt.Println(dict["a"])
• 使用make函数创建
dict1 := make(map[int]int)
dict2 := make(map[int]int, 10) //初始化容量是10
dict1[1]=1
dict2[1]=1
• map标准操作
d1 := make(map[string]string, 10)
// 1. 赋值
d1["name"] = "chs"
// 2. 访问值
fmt.Println(d1["name"])
// 3. range遍历, 但是不能保证每次遍历的顺序是一样的
for k, v := range mp {
fmt.Println("k=", k, "v=", v)
}
// 4. 删除值
delete(d1, "name")
• map特殊操作
Go内置的map不是并发安全的
// 如果map的value是一个复合对象,当修改复合对象的值时候,需要整体替换这个复合对象
type User struct {
name string,
arg int,
}
dict := make(map[string]User)
user := User{
name: "chs",
age: 18,
}
dict["chs"] = user
// dict["chs"].age = 29 //错误
user.age = 29
dict["chs"] = user //整体替换value
• struct
结构的类型可以是任意类型,而且它的存储空间是连续的,其中字段按照声明的顺序存放
struct的有两种形式:
• struct类型的字面量
struct {
FieldName FieldType,
FieldName FieldType,
}
• 自定义struct类型
type TypeName struct {
FieldName FieldType,
FieldName FieldType,
}
struct字面量用的不是很多,大多使用自定义类型的struct类型
• struct类型变量的初始化
package main
import "fmt"
type Person struct {
name string
age int
}
type Student struct {
*Person
number int
}
func main() {
p := &Person{
name: "chs",
age: 28,
}
s := Student{
Person: p,
number: 110,
}
fmt.Println(s.age) //这里Student通过struct间接继承了Person
}
参考<<Go语言核心编程>>