理论介绍
数组&切片
在go语言的复合数据类型中,需要认识两种必要的数据类型
- 数组
- 切片
数组跟切片都是指一系列同一类型数据的结合。数组中包含的每个数据被称为数组元素,一个数组包含的元素个数成为数组的长度。不过,在go语言中数组与切片有一个很大的区别,数组长度在定义后不可更改,数组声明的时候指定的元素个数,就是此数组添加元素的上限数目。
切片可以动态扩充存放空间,可以被随意传递不会导致管理的元素被复制。相比数组,切片是开发中更多的被用到的数据类型。
不管是数组还是切片,在go语言中使用都非常简单,下面通过实际的代码案例来看看,数组跟切片的使用
数组的性质:
- 访问元素容易
- 更新困难
代码实战
# array.go
package common
import (
"fmt"
)
func Arr() {
a := [2] int{1, 2} // 数组, 一开始就分配好了内存,大小限定,不能拓展
b := []int{1, 2, 3, 4, 5, 6, 7} // 切片,大小没有限定,可以动态拓展
for _, i := range a{
fmt.Printf("a 数组遍历 %d\n", i)
}
for _, j := range b{
fmt.Printf("b 切片遍历 %d\n", j)
}
// 输出数组的第二个元素
fmt.Printf("a的第二个元素 %d\n", a[1])
// 输出切片的第五个元素
fmt.Printf("b的第五个元素 %d\n", b[4])
}
在上述代码中,我们分别声明了数组跟切片,并分别进行了遍历与访问,操作都有注释,可以直接看代码注释理解。
代码测试
# main.go
package main
import "github.com/csunny/argo/src/common"
func main() {
common.Arr()
}
在go语言中程序包的入口是main包, 函数的入口是main函数,所以代码中我们在main包里面有个main函数,通过main函数执行我们的代码。 在go中引入一个包用的是import,后面跟的是包的路径。
注意 go语言中的私有、公有变量是直接根据命名规则来区分的,小写为私有、大写为公有。所以我们在这里Arr首字母用的是大写,这样我们Arr就是一个公有变量,可以在其他包里面直接引用。
链表
相比数组,链表是要稍微复杂一点的数据结构。链表是一种线性表,但是不会按照线性的顺序存储数据,而是在每一个节点里面存到写一个节点的指针。链表的特性:
- 插入元素容易
- 元素访问困难
代码实战
package linklist
import (
"fmt"
"log"
)
// Item 可以理解为范性,也就是任意的数据类型
type Item interface {
}
// 一个节点,除了自身的数据之外,还必须指向下一个节点,尾部节点指向为nil
type LinkNode struct {
Payload Item // Payload 为任意数据类型
Next *LinkNode
}
// go语言方法,对比与下面的NewLinkNode,方法可以理解为面向对象里面对象的方法,虽然实现的功能
// 跟函数类似,但是方式是绑定在对象上的,也就是说我们此处的Add是绑定与head这个LinkNode对象的。
// 这个是go语言区别与其他语言的设计方式,也是go语言很重要的一部分。
func (head *LinkNode) Add(payload Item) {
// 这里采用尾部插入的方式,给链表添加元素
point := head
for point.Next != nil{
point = point.Next
}
newNode := LinkNode{payload, nil}
point.Next = &newNode
// 头部插入
//newNode := LinkNode{payload, nil}
//newNode.Next = head
}
// 创建一个新的链表。 函数,对比与上面的方法,函数是没有绑定任何对象的。
// go语言的函数需要指明参数跟返回值,在此函数中,我们的参数是length,返回值是一个LinkNode对象
// 除了绑定之外,函数跟方法并没有什么不同
func NewLinkNode(length int) *LinkNode {
if length <= 0{
fmt.Printf("链表长度必须大于0")
log.Panic("链表长度必须大于0")
}
var head *LinkNode
head = &LinkNode{}
for i := 0; i<length; i++{
var newNode *LinkNode
newNode = &LinkNode{Payload: i}
newNode.Next = head
head = newNode
}
return head
}
在代码中,我们首先创建了一个LinkNode对象,一个LinkNode对象包含两个元素,一个是Payload(参数)另一个是Next也就是下一个节点。 我们用go语言的语法,实现了一个Add方法,此方法可以用于添加元素。在一个链表中添加元素可以采用头部插入,或者尾部插入。当然中间插入也是可行的,只需要将之前的链接断开,然后重新链接就可以了。
NewLinkNode,用于创建一个指定长度的链表,接收一个int类型的参数,返回链接的头节点。详细的内容可以看注释。以下为测试代码:
package linklist
import "testing"
func TestLinkNode_Add(t *testing.T) {
head := NewLinkNode(10)
for head.Next != nil{
t.Errorf("%s", head.Payload)
head = head.Next
}
}
测试代码我们对链表进行了遍历,输出我们放在了error里面,大家可以运行go test查看输出。以上就是简单的关于go语言对数组跟链表的介绍。