Go语言基础 - 复合数据类型

148 阅读5分钟

复合数据类型

上一篇文章中我们学习了Go语言的基本数据类型,就和Java一样有8种基本数据类型一样,大致可以将这些基本数据类型分为整数型、浮点型、字符型、布尔型数据。接下来我们来学习Go语言的复合数据类型,以下是各种复合数据类型的特点和使用场景:

  1. 数组
  • 特点:数组是一种固定长度、同一类型的数据结构,在声明时需要指定长度。
  • 使用场景:适合用于存储具有固定数量的同类型数据,例如存储一组坐标、一组成绩等。
  1. 切片
  • 特点:切片是一种引用类型的动态数组,它的长度可以随时改变,不需要在声明时指定长度。
  • 使用场景:适合用于存储动态长度的同类型数据,例如存储日志、读取大文件、传输网络数据等。
  1. 映射
  • 特点:映射是一种无序的键值对数据结构,在声明时无需指定长度,可以动态增删改查键值对。
  • 使用场景:适合用于存储需要通过键值来访问的数据,例如存储字典、存储用户信息等。
  1. 结构体
  • 特点:结构体是一种复合数据类型,可以将不同类型的数据组合在一起,形成一个自定义的数据类型,可以包含字段和方法
  • 使用场景:适合用于存储一组相关的数据,例如存储人的信息、存储车辆的信息等。
  1. 接口
  • 特点:接口是一种抽象数据类型,定义了一个对象的行为,而不关心对象的具体类型,可以被不同的对象实现。
  • 使用场景:适合用于实现多态性、接口隔离原则、依赖倒置原则等面向对象的编程概念,例如定义一个通用的排序函数,可以接受不同的数据类型并进行排序。

数组

// 定义一个长度为5的int类型数组
var arr [5]int

// 定义一个长度为5的int类型数组,并且赋初始值
//var arr = [5]int{1, 2, 3, 4, 5}

// 给数组的第三个元素赋值
arr[2] = 3

// 打印数组
fmt.Println("array:", arr)

// 打印数组长度
fmt.Println("array length: ", len(arr))

image.png

未赋值的下标处默认为0,和java是一样的

切片

切片其实的是对底层数组的封装,可以就看作是数组,但是他相对于数组优点是可以扩容,这里可以类比Java的ArrayList

// 定义一个空的切片
var slice []int

// 使用make函数初始化一个有3个元素的int类型切片
slice = make([]int, 3)
slice[0] = 1
slice[1] = 2
slice[2] = 3

fmt.Println("slice init: ", slice)
// 获取切片的长度和容量
var lenOfSlice int = len(slice)
var capOfSlice int = cap(slice)

fmt.Println("lenOfSlice init: ", lenOfSlice)
fmt.Println("capOfSlice init: ", capOfSlice)

// 添加元素到切片尾部
slice = append(slice, 4)

fmt.Println("slice append: ", slice)
// 获取切片的长度和容量
lenOfSlice = len(slice)
capOfSlice = cap(slice)

fmt.Println("lenOfSlice append: ", lenOfSlice)
fmt.Println("capOfSlice append", capOfSlice)

// 将切片从索引1开始到索引3的元素删除,然后,将索引的
/**
这段代码的意思是从 slice 中移除第 2 和第 3 个元素,然后将第 1 个元素和剩余的元素组成新的切片。
具体实现上,代码将 slice 切片中下标为 1 到 2(不包括第 2 个元素)的部分和下标为 3 开始到结尾的部分连接起来,
最后将结果重新赋值给 slice 变量。这个操作使用了可变参数函数 append 将两个切片连接起来。
*/
slice = append(slice[:1], slice[:3]...)

fmt.Println("slice remove: ", slice)

// 获取切片的长度和容量
lenOfSlice = len(slice)
capOfSlice = cap(slice)

fmt.Println("lenOfSlice remove: ", lenOfSlice)
fmt.Println("capOfSlice remove: ", capOfSlice)

// 切片迭代
for index, value := range slice {
   fmt.Printf("index: %d,value: %d\n", index, value)
}

image.png

映射

映射是一种通过键值对存储数据,用途是根据key值快速查找到的对应的value,和Java中的HashMap很像,但是HashMap如果根据key值找不到value值会返回null值,而Go语言的映射会返回该Value值数据类型的默认值,例如value值的类型为int,那么如果根据key找不到数据时,会返回0

// 定义一个映射
var m map[string]int
m = make(map[string]int)

// 插入数据
m["apple"] = 1
m["banana"] = 2
m["orange"] = 3

// 查找数据
fmt.Println("apple:", m["apple"])
fmt.Println("banana:", m["banana"])
fmt.Println("orange:", m["orange"])

// 删除数据
delete(m, "banana")
fmt.Println("banana:", m["banana"])

// 判断数据是否存在
value, ok := m["banana"]
fmt.Println("banana exists:", ok, ",value: ", value)

// 遍历映射
for key, value := range m {
   fmt.Println(key, ":", value)
}

image.png

结构体

结构体是一种自定义的数据类型,可以和Java的class类对比,它既有属性,也有方法。

// 定义一个结构体
type Person struct {
   name   string
   age    int
   gender string
}

// 创建一个 Person结构体的实例
var p Person = Person{name: "jack", age: 20, gender: "male"}

// 访问结构体字段
fmt.Println("name: ", p.name)
fmt.Println("age: ", p.age)
fmt.Println("gender: ", p.gender)

// 修改结构体字段
p.age = 25
fmt.Println("age modiffied: ", p.age)
   
// 指针访问
var pp *Person = &p

// 通过指针访问和修改结构体字段
fmt.Println("Name (via pointer):", pp.name)
pp.name = "Jerry"
fmt.Println("Modified name (via pointer):", pp.name)

image.png

接口

接口的作用是定义一组方法,其实和Java的接口差不多,区别就是Go语言的接口中不能加静态属性

// 定义一个接口

type Animal interface {
   speak() string
}

// 定义一个结构体
type Dog struct {
   name string
}

// 实现Animal接口的方法
func (d Dog) speak() string {
   return "汪汪汪"
}

// 定义另一个结构体
type Cat struct {
   name string
}

// 实现Animal接口方法
func (c Cat) speak() string {
   return "喵喵喵"
}

// 定义一个Aninal类型的变量
var animal Animal

// 将Dog类型的变量赋值给Animal类型的变量
animal = Dog{name: "小黄"}

// 调用Dog类型的speak方法,输出 '汪汪汪'
fmt.Println(animal.speak())

// 将Cat类型的变量赋值给Animal类型的变量
animal = Cat{name: "小白"}

// 调用speak方法,输出 "喵喵喵"
fmt.Println(animal.speak())