Go基础语法-3 | 青训营笔记
Go 语言的设计目的是作为 C/C++ 的替代工具,是谷歌内部为了解决 C/C++ 开发中的一些痛点:编译慢、不受控制的依赖、三方库混乱、编程范式繁多(每个人都选择其中一部分特性)、并发编程麻烦、跨平台代码兼容、内存安全、工程开发效率低等等。
目录
- <函数>
- <结构体>
- <切片>
- <集合>
Go函数
入口函数:main()
函数定义如下:
func function_name( [parameter list] ) [return_types] {
函数体
}
调用与c类似,多了值传递或者引用传递,或者传递指针变量
可以方便的返回多个值,和Python类似
函数闭包
每调用一个函数,调用出的函数内的变量初始化一次,相当于每个函数分别独立封闭;
package main
import "fmt"
func getSequence() func() int {
i := 0
return func() int {
i += 1
return i
}
}
func main() {
// nextNumber 为一个函数,函数 i 为 0
nextNumber := getSequence()
// 调用 nextNumber 函数,i 变量自增 1 并返回
fmt.Print(nextNumber())
fmt.Print(nextNumber())
// 创建新的函数 nextNumber1,并查看结果
nextNumber1 := getSequence()
fmt.Print(nextNumber1())
fmt.Print(nextNumber())
}
//运行结果:1213
函数变量
Go中函数可以直接作为变量使用
方法函数
func (variable_name variable_data_type) function_name() [return_type]{
//函数体
}
package main
import (
"fmt"
)
type Circle struct {
radius float64
}
func main() {
var c1 Circle
c1.radius = 10.00
fmt.Println("圆的面积 = ", c1.getArea())
}
func (c Circle) getArea() float64 {
return 3.14 * c.radius * c.radius
}
结构体
声明结构体
结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。type 语句设定了结构体的名称。结构体的格式如下:
type struct_variable_type struct {
member definition
member definition
...
member definition
}
variable_name := structure_variable_type {value1, value2...valuen}//必须按定义顺序
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
访问结构体成员
如果要访问结构体成员,需要使用点号 . 操作符,格式为:
结构体.成员名
注意没有->操作符,使用结构体指针访问结构体成员,同样使用 . 操作符
结构体更加类似于java中的类型,而非结构体。
package main
import "fmt"
type Books struct {
title string
author string
book_id int
}
func main() {
var Book1 Books
var Book2 Books
Book1.title = "homo青春修炼手册"
Book1.author = "哼哼哼啊啊啊啊啊啊"
Book1.book_id = 114514
Book2.title = "6"
Book2.author = "feellmoose"
Book2.book_id = 666666
printBook(&Book1)
printBook(&Book2)
}
func printBook(book *Books) {
fmt.Printf("Book title : %s\n", book.title)
fmt.Printf("Book author : %s\n", book.author)
fmt.Printf("Book book_id : %d\n", book.book_id)
}
Slices(切片)
使用Go切片
Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
Go语言中,数组和切片有以下区别:
- Go 语言切片是对数组的抽象,功能更加强大;
- 切片是指针类型,数组是值类型;
- 数组的长度是固定的,而切片不是(切片可以看成动态的数组);
- 切片比数组多一个容量(cap)属性;
- 切片的底层是数组切片是引用类型,因此在当传递切片时将引用同一指针,修改值将会影响其他的对象当切片和数组作为参数在函数中传递时。数组传递的是值,而切片传递的是指针切片基于数组,但提供了更高的灵活性,可以使用范围来截取切片
切片有着比数组更加广泛的用途,优点:
- 可以用来实现动态数组;
- 引用传递,可以直接改变原值,在容量过大时避免了值传递的开销
定义切片
- 声明一个未指定大小的数组来定义切片
var identifier []type
- 使用
make()函数来创建切片( make()函数是go语言的一个内置函数。只用于channel,map和slice的创建 )
var slice1 []type = make([]type, len)
slice1 := make([]type, len)//不需要添加len
具体方法如下:
make([]T, length, capacity)
空(nil)切片
一个切片在未初始化之前默认为 nil,长度为 0
初始化切片
- 直接初始化切片, [] 表示是切片类型,其 cap=len
s :=[] int {1,2,3}
- 通过数组初始化,将数组中从下标 第一个下标 到 第二个小标的前一个 元素创建为一个新的切片,可以省略前后任意一个或者两个参数
s := arr[startIndex:endIndex]
- 通过切片初始化,将切片中从下标 第一个下标 到 第二个小标的前一个 元素创建为一个新的切片
s1 := s[startIndex:endIndex]
- 通过内置函数 make() 初始化切片s, []int 标识为其元素类型为 int 的切片。
s :=make([]int,len,cap)
append() 和 copy() 函数
增加切片容量:如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。
Map(集合)
Map 是一种无序的键值对的集合,可以通过 key 来快速检索数据,key 类似于索引,指向数据的值
在Go中我们可以像迭代数组和切片那样迭代它。遍历 Map 时返回的键值对的顺序是不确定的
在获取 Map 的值时,如果键不存在,返回该类型的零值,例如 int 类型的零值是 0,string 类型的零值是 ""。
Map 是引用类型,如果将一个 Map 传递给一个函数或赋值给另一个变量,它们都指向同一个底层数据结构,因此对 Map 的修改会影响到所有引用它的变量。
定义集合
- 使用内建函数 make 或使用 map 关键字来定义 Map
// 使用 make 函数
map_variable := make(map[KeyType]ValueType, initialCapacity)
其中 KeyType 是键的类型,ValueType 是值的类型,initialCapacity 是可选的参数,用于指定 Map 的初始容量。Map 的容量是指 Map 中可以保存的键值对的数量,当 Map 中的键值对数量达到容量时,Map 会自动扩容。如果不指定 initialCapacity,Go 语言会根据实际情况选择一个合适的值。
- 使用字面量直接定义并初始化 Map:
// 使用字面量创建 Map
m := map[string]int{
"apple": 1,
"banana": 2,
"orange": 3,
}
使用集合
- 获取元素:
// 获取键值对
v1 := m["apple"]
v2, ok := m["pear"] // 如果键不存在,ok 的值为 false,v2 的值为该类型的零值
- 修改元素:
// 修改键值对
m["apple"] = 5
- 获取 Map 的长度:
// 获取 Map 的长度
len := len(m)
- 遍历 Map:
// 遍历 Map
for k, v := range m {
fmt.Printf("key=%s, value=%d\n", k, v)
}
- 删除元素:
// 删除键值对
delete(m, "banana")