GO语言基础笔记(二):控制结构与函数
2023-12-26 03:57:17
1. 控制结构
1.1 if-else 结构
- 基本形式:
if
条件判断后跟着一个代码块。如果条件为真,则执行该代码块。 - else 语句:紧随
if
代码块后面,当if
条件不成立时执行。 - else if:可以在
if
和else
之间添加更多的条件判断。
package main
import (
"fmt"
)
func main() {
score := 85 // 假设这是一个成绩
// 使用 if 判断成绩是否优秀
if score >= 90 {
fmt.Println("成绩优秀,等级:A")
} else if score >= 80 {
// 当成绩不满足第一个 if 条件(即小于90),但满足 else if 条件时执行
fmt.Println("成绩良好,等级:B")
} else if score >= 70 {
fmt.Println("成绩合格,等级:C")
} else if score >= 60 {
fmt.Println("成绩及格,等级:D")
} else {
// 当所有其他条件都不满足时执行 else 块
fmt.Println("成绩不及格,等级:F")
}
}
- 条件清晰:每个
if
和else if
块的条件应该是互斥的,这样可以防止重复判断。- 顺序安排:将最有可能发生的条件放在前面,可以提高代码效率。
- 避免嵌套过深:尽量减少
if-else
的嵌套深度,以保持代码的可读性。- 条件简化:在条件判断中使用适当的逻辑运算符来简化表达式。
1.2 switch 结构
- 基本用法:
switch
后跟一个表达式,然后是多个case
分支。每个case
后跟着要比较的值和执行的代码块。 - 不带表达式的 switch:可以直接在
case
后使用条件表达式。 - fallthrough 关键字:默认情况下,每个
case
执行完后自动跳出switch
,使用fallthrough
可以强制执行下一个case
。
?
package main
import (
"fmt"
)
func main() {
// 示例1:基本用法
number := 3
switch number {
case 1:
fmt.Println("数字是 1")
case 2:
fmt.Println("数字是 2")
case 3:
fmt.Println("数字是 3")
default:
fmt.Println("数字不是 1、2、3")
}
// 示例2:不带表达式的switch
score := 85
switch {
case score >= 90:
fmt.Println("成绩优秀")
case score >= 80:
fmt.Println("成绩良好")
case score >= 60:
fmt.Println("成绩合格")
default:
fmt.Println("成绩不合格")
}
// 示例3:使用fallthrough
month := 5
switch month {
case 3, 4, 5:
fmt.Println("春季")
fallthrough
case 6, 7, 8:
fmt.Println("夏季")
case 9, 10, 11:
fmt.Println("秋季")
case 12, 1, 2:
fmt.Println("冬季")
default:
fmt.Println("未知的月份")
}
}
?
- 明确case分支:每个
case
后面跟着一个或多个要比较的值和代码块。这使得代码逻辑清晰易懂。- 使用default:当所有
case
都不匹配时,执行default
分支。这是一个良好的编程习惯,可用于处理异常或未预期的情况。- 不带表达式的switch:在某些情况下,不带表达式的
switch
可以替代多层嵌套的if-else
,使得代码更加清晰。- 谨慎使用fallthrough:
fallthrough
关键字使得控制流穿越到下一个case
,即使下一个case
的条件不成立也会执行。使用时要非常小心,以避免逻辑错误。
1.3 for 循环
- 基本结构:包括初始化语句、条件表达式和结束后的操作,格式为
for 初始化; 条件; 后续操作 {}
。 - 条件循环:只有条件表达式的
for
循环。 - 无限循环:省略所有元素的
for
循环将无限循环直到内部有break
或return
。
????????1. 基本的for循环
package main
import (
"fmt"
)
func main() {
// 示例1:基本的for循环
for i := 0; i < 5; i++ {
fmt.Println("基本循环,当前索引:", i)
}
}
?????????2. 条件循环
// 示例2:条件循环
j := 0
for j < 5 {
fmt.Println("条件循环,当前索引:", j)
j++
}
????????3. 无限循环?
// 示例3:无限循环
k := 0
for {
if k == 3 {
break // 当 k 等于 3 时退出循环
}
fmt.Println("无限循环,当前索引:", k)
k++
}
}
技巧性总结
- 明确循环条件:在编写
for
循环时,始终清晰地定义循环的开始和结束条件。- 避免无限循环:在使用无限循环时,务必确保有一个明确的退出条件,以避免程序陷入死循环。
- 代码简洁:尽量保持循环体内代码的简洁,这有助于提高代码的可读性和可维护性。
2. 函数
2.1 函数定义
- 基本语法:
func 函数名(参数列表) (返回值列表) { 函数体 }
。 - 参数列表:定义输入的类型和名称。
- 返回值列表:可以是具名的也可以是非具名的,具名返回值在函数体开始时被自动初始化。
????????基本函数定义
package main
import (
"fmt"
)
// 无参数,无返回值的函数
func greet() {
fmt.Println("Hello, Go!")
}
func main() {
greet() // 调用函数
}
?????????带参数的函数
// 带参数的函数
func add(x int, y int) int {
return x + y
}
func main() {
result := add(5, 7) // 调用函数
fmt.Println("结果:", result)
}
?????????具名返回值
// 具名返回值
func swap(x, y string) (a, b string) {
a = y
b = x
return // 隐式返回a, b
}
func main() {
a, b := swap("hello", "world")
fmt.Println(a, b) // 输出:world hello
}
//使用具名返回值可以提高代码的可读性,尤其是在函数有多个返回值时。
????????非具名返回值?
// 非具名返回值
func divide(x, y float64) (float64, error) {
if y == 0.0 {
return 0.0, fmt.Errorf("不能除以零")
}
return x / y, nil
}
func main() {
result, err := divide(10.0, 0.0)
if err != nil {
fmt.Println("错误:", err)
} else {
fmt.Println("结果:", result)
}
}
- 清晰的参数和返回值:定义函数时,明确参数类型和返回值类型可以提高代码的可读性和健壮性。
- 合理使用具名返回值:在函数返回多个值或需要说明返回值意义时使用具名返回值。
- 错误处理:在可能出现错误的场合,返回一个错误值作为函数的一部分,以便于错误处理。
2.2 函数使用
- 调用函数:使用函数名和传入相应的参数。
- 返回值:可以返回一个或多个值。
- 匿名函数:没有函数名的函数,可以在定义后立即调用。
????????调用普通函数
package main
import (
"fmt"
)
// 定义一个简单的相加函数
func add(x, y int) int {
return x + y
}
func main() {
// 调用函数并处理返回值
result := add(5, 7)
fmt.Println("相加结果:", result)
}
?????????处理多个返回值
// 定义一个函数,返回两个值
func divideAndRemainder(x, y int) (int, int) {
return x / y, x % y
}
func main() {
// 接收两个返回值
quotient, remainder := divideAndRemainder(7, 2)
fmt.Println("商:", quotient, "余数:", remainder)
}
?????????使用匿名函数
func main() {
// 定义并立即调用匿名函数
func(msg string) {
fmt.Println(msg)
}("Hello, Go!")
}
- 函数调用的准确性:在调用函数时,确保参数的正确性和返回值的正确处理。
- 处理多返回值:在函数返回多个值时,可以通过多个变量来接收这些值。
- 匿名函数的灵活性:匿名函数是一种灵活的工具,可以用于立即执行一些操作,或作为高阶函数的参数。
2.3回调函数
package main
import (
"fmt"
)
// 定义回调函数类型,这种函数接受一个整数并返回一个整数
type callbackFunc func(int) int
// processSlice 函数接受一个整数切片和一个回调函数
// 它对切片中的每个元素应用回调函数,并返回新的切片
func processSlice(slice []int, callback callbackFunc) []int {
var result []int
for _, value := range slice {
processedValue := callback(value)
result = append(result, processedValue)
}
return result
}
// 具体的回调函数,例如将整数乘以2
func multiplyByTwo(n int) int {
return n * 2
}
func main() {
// 定义一个整数切片
slice := []int{1, 2, 3, 4, 5}
// 使用 multiplyByTwo 回调函数处理切片
processedSlice := processSlice(slice, multiplyByTwo)
// 打印原始和处理后的切片
fmt.Println("原始切片:", slice)
fmt.Println("处理后的切片:", processedSlice)
}
?
????????在这个示例中,我们定义了一个事件管理器eventManager
,它允许注册回调函数并在事件触发时调用这些函数。?
package main
import (
"fmt"
)
// 定义回调函数类型
type eventCallback func()
// 事件管理器
type eventManager struct {
callbacks []eventCallback
}
// 注册事件的回调函数
func (m *eventManager) registerCallback(callback eventCallback) {
m.callbacks = append(m.callbacks, callback)
}
// 触发事件,调用所有注册的回调函数
func (m *eventManager) triggerEvent() {
for _, callback := range m.callbacks {
callback()
}
}
func main() {
// 创建事件管理器实例
manager := eventManager{}
// 注册一些回调函数
manager.registerCallback(func() {
fmt.Println("第一个事件回调被触发")
})
manager.registerCallback(func() {
fmt.Println("第二个事件回调被触发")
})
// 触发事件
manager.triggerEvent()
}
?
?2.3 go的其他函数机制
-
多返回值:Go函数可以返回多个值,这在错误处理和数据返回方面非常有用。
-
命名返回值:函数可以有命名的返回值,这些返回值在函数开始时就被声明,可以在函数体内直接使用。
-
变参函数(Variadic Functions):Go支持变参函数,允许函数接受任意数量的参数。
-
匿名函数和闭包(Closures):Go支持匿名函数,这些函数可以定义在其他函数内部,并可以访问外部函数的变量,形成闭包。
-
延迟调用(Defer):Go的
defer
语句会延迟函数的执行直到包含它的函数结束。 -
高阶函数(Higher-Order Functions):在Go中,函数可以作为参数传递给其他函数,也可以作为其他函数的返回值。
-
方法(Methods):Go允许定义在结构体(或任意类型)上的函数,称为方法。这提供了一种面向对象的方式来处理数据。
-
接口(Interfaces):虽然不是直接的函数机制,但接口在Go中用于定义函数的行为契约,为多态和模块化设计提供支持。
-
递归函数(Recursive Functions):函数可以调用自身,这是在处理某些算法时非常有用的。
-
并发的函数调用(Goroutines):通过
goroutines
,Go支持在轻量级线程中并发执行函数。
?
文章来源:https://blog.csdn.net/weixin_44120785/article/details/135177020
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!