这是在我学习过程中记录的一些有关复杂数据类型使用的笔记
一、数组
声明一个长度为的整形数组,给数组元素赋值,同时查看数组长度
var a [5]int
a[3] = 100
fmt.Println(a[3], len(a))
}
声明数组的同时初始化数组
b := [4]int{4, 5, 6, 7}
声明一个整形的二维数组
var twoD [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
twoD[i][j] = i + j
}
}
fmt.Println("2d: ", twoD)
二、切片类型
在Go语言中,切片(slice)是一种动态长度的数据结构,它提供了对数组部分元素的引用。切片是基于数组的抽象,可以方便地操作和管理变长的序列。
切片的基本语法如下:
var slice []T
其中,T 是切片中元素的类型。你也可以使用 make 函数来创建一个空的切片。
声明一个切片类型的变量s,使用make初始化,它的长度为三
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
切片的长度是可变的,我们可以使用append增加元素
s = append(s, "d")
fmt.Println(len(s))
fmt.Println(s[2], len(s))
s = append(s, "e", "f")
fmt.Println(s)
使用copy函数对切片元素进行复制操作
c := make([]string, len(s))
copy(c, s)
fmt.Println(c)
取出切片中第m-n个元素,这包含头部不包含尾部
fmt.Println(s[2:5])
fmt.Println(s[:5])
fmt.Println(s[2:])
三、map
在Go语言中,map 是一种用于存储键值对的数据结构,类似于其他编程语言中的字典、哈希表或关联数组。map 提供了快速的键值查找和更新操作。
使用 map 的基本语法如下:
var m map[keyType]valueType
其中,keyType 是键的类型,valueType 是值的类型。你也可以使用 make 函数来创建一个空的映射。
//用make创建一个map,key的类型为string,value的类型为int
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m)
fmt.Println(len(m))
fmt.Println(m["one"])
//不存在的键值对
fmt.Println(m["unknow"])
//检查map中是否有某个key存在
r, ok := m["one"]
fmt.Println(r, ok)
//删除键值对
delete(m, "one")
r, ok = m["one"]
fmt.Println(r, ok)
m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
四、函数
在Go语言中,函数(function)是一种可执行的代码块,它接受一些输入参数并返回一个结果。函数可以被定义和调用,用于模块化和重用代码。
以下是一个简单的函数示例:
func add(a, b int) int {
return a + b
}
上述示例定义了一个名为 add 的函数,它接受两个整数类型的参数 a 和 b,并返回它们的和。
函数的基本语法如下:
func functionName(parameter1 type, parameter2 type) returnType {
// 函数体
return result
}
其中,functionName 是函数的名称,parameter1、parameter2 是函数的参数,returnType 是函数的返回值类型。函数体内部包含了要执行的代码逻辑,并使用 return 语句返回结果。
函数可以有多个参数,也可以有多个返回值,改写成(returnType1,returnType2)。如果函数没有返回值,可以省略 returnType。
五、结构体
在Go语言中,结构体(Struct)是一种用户自定义的数据类型,用于封装一组相关的字段。它可以包含不同类型的字段,这些字段可以是基本类型、复合类型(如切片、映射和其他结构体)或者函数类型。
结构体定义使用关键字type,后面跟着结构体名称和字段列表。每个字段由字段名称和字段类型组成,字段之间使用逗号分隔。
我们定义一个这样的结构体
type user struct {
name string
age int
}
下面是相关操作
//声明结构体
a := user{
name: "tom",
age: 18,
}
fmt.Println(a)
b := user{"tom", 19}
fmt.Println(b)
//只初始化一个数据
c := user{age: 15}
c.name = "tom"
var d user
d.name = "aaa"
d.age = 16
六、通道
在Golang中,通道(Channel)是一种用于在不同goroutine之间进行通信和同步的机制。通道允许一个goroutine发送特定类型的数据给另一个goroutine,同时还提供了同步操作,以确保数据在发送和接收之间的正确传递。
以下是一些关于Golang中通道的重要概念:
- 创建通道: 你可以使用内置的
make函数来创建一个通道,指定通道中元素的类型。例如:ch := make(chan int)将创建一个整数类型的通道。 - 发送和接收数据: 使用箭头操作符
<-来发送和接收数据。发送数据到通道时,可以使用<-操作符:ch <- data。从通道接收数据时,也可以使用<-操作符:data := <- ch。注意,发送和接收操作会阻塞当前goroutine,直到另一个goroutine准备好进行对应的操作。 - 关闭通道: 通过调用内置的
close函数,可以关闭一个通道:close(ch)。关闭通道后,无法再向其发送数据,但仍然可以从通道接收已有的数据。接收操作可以通过额外的第二个返回值来判断通道是否已经关闭。 - 阻塞和非阻塞操作: 默认情况下,通道的发送和接收操作都是阻塞的,即在发送或接收前,goroutine会被阻塞。但可以使用
select语句和default分支来实现非阻塞的通道操作。 - 单向通道: Golang还提供了单向通道,用于限制通道的发送或接收操作。可以通过类型转换将一个双向通道转换为只发送或只接收的单向通道。例如:
ch := make(chan<- int)表示只发送的通道,ch := make(<-chan int)表示只接收的通道。
下面是一个使用通道channel的简单例子,输出0-9的平方
//src := make(chan int) 创建了一个无缓冲的整型通道 src。无缓冲通道意味着发送和接收操作将会同步阻塞,直到发送方和接收方都准备好进行数据交换。
src := make(chan int)
//dest := make(chan int, 3) 创建了一个有缓冲大小为3的整型通道 dest。有缓冲通道允许在通道中存储一定数量的元素,而不会立即阻塞发送方。
//只有当通道的缓冲区满时,发送操作才会阻塞。
dest := make(chan int, 3)
go func() {
defer close(src)
//发送数据
for i := 0; i < 10; i++ {
//channel的赋值方式
src <- i
}
}()
//src接收,dest发送
go func() {
//这是在函数中,执行到这里时,会将defer后面语句压入栈中,连同数据也压入栈中了。当函数执行完毕后,再执行这里的语句
defer close(dest)
for i := range src {
dest <- i * i
}
}()
//主函数中的range dest循环会一直阻塞,直到dest通道被关闭。在每次循环迭代中,它会接收dest通道中的值,并将其打印出来。
for i := range dest {
println(i)
}