常用特性
函数
函数是一段封装了特定功能的代码,可以接收零个或多个参数,并返回零个或多个结果。在 Go 语言中,函数是一种一等公民,可以作为参数或返回值传递,也可以赋值给变量或作为结构体或接口的方法。
函数的定义使用关键字 func,后跟函数名、参数列表、返回值列表和函数体。例如:
func add(a int, b int) int {
return a + b // 返回 a 和 b 的和
}
func swap(a, b string) (string, string) {
return b, a // 返回 a 和 b 的交换
}
func hello() { // 定义一个名为 hello 的函数,不接收任何参数,也不返回任何结果
fmt.Println("Hello, world!") // 打印 "Hello, world!"
}
函数的调用使用函数名和实参列表,可以将返回值赋值给变量或直接使用。例如:
c := add(1, 2) // 调用 add 函数,传入 1 和 2 作为实参,将返回值赋值给变量 c
fmt.Println(c) // 打印 c 的值
d, e := swap("Go", "lang") // 调用 swap 函数,传入 "Go" 和 "lang" 作为实参,将返回值赋值给变量 d 和 e
fmt.Println(d, e) // 打印 d 和 e 的值
hello() // 调用 hello 函数,不传入任何实参,也不使用任何返回值
函数的参数可以是值传递或引用传递,取决于参数的类型。值传递表示函数内部对参数的修改不会影响外部的变量,而引用传递表示函数内部对参数的修改会影响外部的变量。一般来说,基本类型和结构体类型是值传递,而切片、映射、通道、指针和接口类型是引用传递。
函数的返回值可以是命名返回值或非命名返回值,取决于是否在返回值列表中指定了变量名。命名返回值表示函数内部可以直接使用返回值变量,并且可以使用 return 关键字省略返回值列表。非命名返回值表示函数内部需要显式地指定返回值列表。
函数的特性包括:
- 可变参数:表示函数可以接收任意数量的同类型参数,使用
...表示可变参数。例如:
func sum(nums ...int) int {
total := 0 // 声明并初始化一个整型变量 total,并赋值为 0
for _, num := range nums { // 使用 for-range 循环遍历 nums 中的每个元素
total += num // 将 total 加上 num
}
return total // 返回 total
}
fmt.Println(sum(1, 2, 3)) // 调用 sum 函数,传入 1, 2, 3 作为实参,打印返回值
fmt.Println(sum(10, 20)) // 调用 sum 函数,传入 10, 20 作为实参,打印返回值
fmt.Println(sum()) // 调用 sum 函数,不传入任何实参,打印返回值
- 匿名函数:表示没有名字的函数,可以在需要时定义和使用。匿名函数可以作为闭包(closure),捕获外部变量的值。例如:
func main() {
a := 10 // 声明并初始化一个整型变量 a,并赋值为 10
f := func() { // 定义一个匿名函数,并赋值给变量 f
fmt.Println(a)
}
f() // 调用 f 函数
a = 20 // 将 a 的值修改为 20
f()
}
- 延迟执行:表示在函数返回前执行一些操作,使用关键字
defer实现。延迟执行常用于清理或释放资源的操作。例如:
func main() {
file, err := os.Open("test.txt") // 打开一个名为 test.txt 的文件,并将文件对象和错误信息赋值给变量 file 和 err
if err != nil { // 如果 err 不为空
fmt.Println(err) // 打印 err 的内容
return // 返回并结束程序
}
defer file.Close() // 使用 defer 关键字延迟执行 file.Close() 方法,在 main 函数返回前关闭文件
data := make([]byte, 100) // 使用 make 函数创建一个长度为 100 的字节切片 data
file.Read(data) // 使用 file.Read 方法读取文件内容到 data 中
fmt.Println(string(data)) // 将 data 转换为字符串并打印
}
并发编程
并发编程是指让程序可以同时执行多个任务,提高程序的性能和响应速度。Go 语言提供了一套原生的并发编程机制,包括 goroutine 和 channel。
- goroutine:表示一种轻量级的线程,可以在一个进程中创建成千上万个,并且可以自动调度和切换。goroutine 的创建使用关键字
go,后跟一个函数或方法调用。例如:
func sayHello() {
fmt.Println("Hello, world!")
}
func main() {
go sayHello() // 使用 go 关键字创建一个 goroutine,并调用 sayHello 函数
time.Sleep(time.Second) // 让主线程休眠一秒,等待 goroutine 执行完毕
}
- channel:表示一种用于在不同 goroutine 之间传递数据的管道,可以实现同步或异步的通信。channel 的创建使用内置函数
make,并指定通道的元素类型。channel 的操作使用<-符号,表示发送或接收数据。例如:
func sum(nums []int, c chan int) { // 定义一个名为 sum 的函数,接收一个整型切片 nums 和一个整型通道 c 作为参数
total := 0 // 声明并初始化一个整型变量 total,并赋值为 0
for _, num := range nums { // 使用 for-range 循环遍历 nums 中的每个元素
total += num // 将 total 加上 num
}
c <- total // 将 total 发送到通道 c 中
}
func main() {
nums := []int{1, 2, 3, 4, 5} // 声明并初始化一个整型切片 nums,并赋值为 [1, 2, 3, 4, 5]
c := make(chan int) // 使用 make 函数创建一个整型通道 c
go sum(nums[:len(nums)/2], c) // 使用 go 关键字创建一个 goroutine,并调用 sum 函数,传入 nums 的前半部分和通道 c 作为参数
go sum(nums[len(nums)/2:], c) // 使用 go 关键字创建另一个 goroutine,并调用 sum 函数,传入 nums 的后半部分和通道 c 作为参数
x, y := <-c, <-c // 分别从通道 c 中接收两个数据,并赋值给变量 x 和 y
fmt.Println(x, y, x + y) // 打印 x,y 和 x + y 的值
}
总结
Go 语言是一种开源的编程语言,由 Google 的 Robert Griesemer, Rob Pike 和 Ken Thompson 在 2007 年设计,并于 2009 年正式发布。Go 语言的设计目标是实现高效、可靠、简洁、易读和跨平台的软件开发。Go 语言的特点包括:
- 静态类型:在编译时确定变量的类型,提高运行效率和安全性。
- 自动垃圾回收:由运行时系统自动管理内存的分配和释放,简化编程的难度。
- 并发编程:提供了原生的 goroutine 和 channel 机制,实现高效的多任务处理。
- 函数式编程:支持函数作为一等公公民,闭包,匿名函数,多返回值,延迟执行等特性。
- 面向接口编程:使用结构体和接口实现面向对象编程,避免了继承带来的复杂性和脆弱性。
Go 语言的基础语法包括:
- 变量和常量:使用
var和const关键字声明变量和常量,并可选地指定类型和初始值。 - 数据类型:包括布尔类型,数值类型,字符串类型,数组类型,切片类型,映射类型,结构体类型,接口类型等。
- 流程控制:包括条件语句,循环语句,选择语句,跳转语句等。
- 函数:使用
func关键字定义函数,并指定参数列表,返回值列表和函数体。
Go 语言的常用特性包括:
- 可变参数:使用
...表示函数可以接收任意数量的同类型参数。 - 匿名函数:表示没有名字的函数,可以在需要时定义和使用,并可以作为闭包捕获外部变量的值。
- 延迟执行:使用
defer关键字表示在函数返回前执行一些操作,常用于清理或释放资源的操作。 - 并发编程:使用
go关键字创建 goroutine,并使用make函数创建 channel,并使用<-符号发送或接收数据。