Golang数组、map、函数及类

数组/切片

数组声明:

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
普通声明:
var arr = [5]int{} // 长度固定为5,不可扩展,{}中为初始值,默认为0
arr := [5]string{"a", "b", "c", "d"}
var arr [5]int // [0, 0, 0, 0]

make关键字声明数组切片:
var arr = make([], 2, 4) // 长度 len(arr) 为2,容量 cap(arr) 为4,长度决定存储量,容量不够时翻倍
arr := make([], 1, 1)
arr = append(arr, 1) // len(arr)=1 cap(arr)=1
arr = append(arr, 2) // len(arr)=2 cap(arr)=2
arr = append(arr, 3) // len(arr)=3 cap(arr)=4

截取、拼接数组:
arr1 :=[]int{1, 2, 3, 4, 5, 6}
arr2 :=[]int{7, 8, 9}
arr1[:3] // 等价于arr1[0:3] => [1, 2, 3]
arr1[3:] // 等价于arr[3:5] => [4, 5, 6]
arr1 = append(arr1, arr2...) // arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]

二维数组:
var arr = [2][2]int{} // [[0, 0], [0, 0]]

遍历:
for index, value := range arr {
fmt.Println(index, value)
}

区别于 javascript:

  • 数组中只能存储相同类型的值
  • 只有make关键字声明的切片长度可变

map

map字典,对应于javascript中的对象,即为键值对的集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
普通声明方式:
var map = map[string]string{
"name": "ludis",
"age": "18",
}
map := map[int]string{
1: "first",
2: "second",
}

make关键字声明:
var map = make(map[string]string) // map == nil
map["name"] = "ludis" // 赋值
delete(map, "name") // 删除
// 判断是否存在某属性
if val, ok := map["name"]; ok {
fmt.Println(val)
fmt.Println(ok)
}

遍历:
for _,value := range map{
fmt.Println(value)
}

函数

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
30
三种函数声明方式:
func function(name string, age int) string{
reutrn name+string(int)
}

var function = func(name string, age int) string{
reutrn name+string(int)
}

function := func(name string, age int) string{
reutrn name+string(int)
}

函数类型为:(去掉函数名及变量名)
func(string, int) string

1、通过func关键字声明的为全局函数,等同于用var声明的全局函数,不能再函数体内用func声明函数
2、在函数体内声明局部函数的方法为 := 简写方式
3、函数声明会提升,变量声明不会提升

回调函数/函数作为参数、函数作为返回值:
func getUserName(name string, f func(name string, age int)){
f(name)
}

func getUserName(name string) func(string){
return func(name string){
fmt.Println(name)
}
}

类与继承、复合、重写

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
类的定义:通过关键字 type 定义
type Animal struct {
age int
weight float64
}

类的方法定义:
func (animal *Animal) setAge(age int){
animal.age = age
}
func (animal *Animal) getWeight() float64{
return animal.weight
}
// 通过 (animal *Animal) 将函数与类绑定,使其成为类的方法
// (animal Animal) 不加地址符时为深拷贝,加地址符为浅拷贝

创建类的对象:
animal := Animal{18, 66.6}
animal.setAge(8) // animal.age = 8
fmt.Println(animal.getWeight()) // 66.6

复合:(汽车有四个轮子、有品牌;轮子有半径。汽车复用轮子类)
type Wheel struct {
r float
}
type Car struct {
wheels [4]intWheel
brand string
}

wheel := Wheel{66.6}
wheels := [4]Wheel{wheel, wheel, wheel, wheel}
car := Car{
wheels: wheels,
brand: "Tesla",
}
fmt.Print(car)

继承:(动物、狗)
type Animal struct {
age int
weight float64
}

func (a *Animal) backAgeAndWeight() (int, float64) {
return a.age, a.weight
}

// 方法重写
func (d *Dog) backAgeAndWeight() (int, float64) {
return d.age, d.weight
}

type Dog struct {
// animal Animal -> Animal 直接继承为自有属性
Animal
name string
age int
}
dog := Dog{
Animal: Animal{5, 6},
name: "二哈",
age: 18,
}
// 继承
fmt.Println(dog.age)
// 复合->模拟继承
fmt.Println(dog.Animal.weight)

// var animal Animal = Dog{}
// 父类的指针指向子类的对象 -> 多态
// go模拟继承,非正真的继承 dog.age != dog.Animal.age,通过复合模拟真正的继承

fmt.Println(dog.Animal.backAgeAndWeight())
fmt.Println(dog.backAgeAndWeight())

go语言中的继承并非正真意义上的继承,而是通过复合的方式模拟继承,当子类继承父类后,子类创建的对象中,包含一个隐藏的父类对象,其中包括父类的属性及方法。当在子类创建的对象中定义重名的属性/方法时,并不会修改父类对象中的属性/方法,而是直接在子类创建的对象上添加,类似javascript中的原型链,当查询对象的属性/方法时,优先在对象上查找,未找到时才会去继承自父类的对象上查找。所以说golang的继承是伪继承。

Author

Ludis

Posted on

2018-01-23

Updated on

2018-02-13

Licensed under

Comments