Golang 02 流程控制 函数
总篇:30
编辑于 2025/6/17 21:00
截稿于: 2025/6/17 23:00
【2025年新版】Go语言教程_Golang入门实战全套视频教程_哔哩哔哩_bilibili
P13-P18
if else
无():
if condition1 {
// do something
} else if condition2 {
// do something else
} else {
// catch-all or default
}
package main
import "fmt"
func main() {
var age int
fmt.Print("请输入您的年龄: ")
_, err := fmt.Scan(&age)
if err != nil {
return
}
if age < 18 {
fmt.Println("child")
} else {
fmt.Println("adult")
}
}
switch
switch后可以是任意表达式,同理case后也是,同样具有default,case 后可以有多个值,或匹配规则.
注意到没有break语句,因为Go的分支穿透需要手动声明fallthrough 穿透到下一个分支
package main
import "fmt"
func main() {
var day int
fmt.Print("day: ")
_, err := fmt.Scan(&day)
if err != nil {
return
}
switch day {
case 1,2,3,4,5:
fmt.Println("work day") //fallthrough
case 6,7:
fmt.Println("rest day")
default:
fmt.Println("other")
}
}
for
Go没有while,循环全都是for
一般的循环同C:
package main
import "fmt"
func main() {
for i := 0; i < 5; i++ {
for j := 0; j < i; j++ {
println(j)
}
}
var i = 5
for i >= 0 {
i = i - 1
fmt.Printf("The variable i is now: %d\n", i)
}
}
无限循环: 以break或continue(两者的区别dddd)跳出循环,C 是for(;😉 Go 对应的就是:
package main
func main() {
var a = 1
// for ; ;{
//
// }
// 以上;;会被格式化省略
for {
if a == 10 {
break //
}
fmt.Println(a)
a++
}
}
for-range
对任何集合都可以遍历,取出pos和对应的val :
for pos,val :=range collection {
//code
}
package main
import "fmt"
func main() {
str := "this is a sentence"
for pos, char := range str {
fmt.Printf("index:%d,val:%c\n", pos, char)
}
}
goto语法已淘汰不赘述
Func 函数
函数入参同C,形参是副本值(传递值)或者指针地址(传递引用),返回值同样要声明类型,以下解释函数的定义方式:
package main
import "fmt"
var num int = 10
var numx2, numx3 int
func main() {
numx2, numx3 = getX2AndX3(num) //同一个包下使用函数
PrintValues()
numx2, numx3 = getX2AndX3_2(num)
PrintValues()
}
func PrintValues() {
fmt.Printf("num = %d, 2x num = %d, 3x num = %d\n", num, numx2, numx3)
}
// 非命名返回值函数 返回多值
func getX2AndX3(input int) (int, int) {
return 2 * input, 3 * input
}
// 命名返回值函数
func getX2AndX3_2(input int) (x2 int, x3 int) {
x2 = 2 * input
x3 = 3 * input
// return x2, x3
return
}
//无参无返回值
func empty_func() {
fmt.Println("empty func")
}
//公共函数,其他包引用本包使用该函数:day02.EmptyFunc()
// 参考fmt.Println
func EmptyFunc(){
fmt.Println("Empty func")
}
传递指针参数的好处在于不需return就可修改原值,坏处在于不安全的操作指针会导致数据错误
package main
import (
"fmt"
)
func Multiply(a, b int, reply *int) {
*reply = a * b
}
func main() {
n := 0
reply := &n
Multiply(10, 5, reply) //直接改变reply的值
fmt.Println("Multiply:", *reply)
}
变长参数,a,b,后面的不确定长度的int参数是一个slice(切片,见03篇):
func myFunc(a, b, arg ...int) {}
package main
import "fmt"
func main() {
x := min(1, 3, 2, 0)
fmt.Printf("The minimum is: %d\n", x)
slice := []int{7,9,3,5,1}
x = min(slice...)
fmt.Printf("The minimum in the slice is: %d", x)
}
func min(s ...int) int {
if len(s)==0 {
return 0
}
min := s[0]
for _, v := range s {
if v < min {
min = v
}
}
return min
}
预感用不到这样的方式
defer
return语句分两步:1.返回值赋值,2.回到调用函数处,在第一步之后就是defer发挥作用的时点,类似于finally
package main
import "fmt"
func main() {
function1()
}
func function1() {
fmt.Printf("In function1 at the top\n")
defer function2()
fmt.Printf("In function1 at the bottom!\n")
}
func function2() {
fmt.Printf("function2: Deferred until the end of the calling function!")
}

除此之外,它可以在任何语句前,表示“注册“一个defer在函数执行完毕前”推迟“执行,且是倒序的,先注册的defer后执行,通常用来做代码参数返回值或执行情况的跟踪
package main
import "fmt"
func trace(s string) { fmt.Println("entering:", s) }
func untrace(s string) { fmt.Println("leaving:", s) }
func a() {
trace("a")
defer untrace("a")
fmt.Println("in a")
}
func b() {
trace("b")
defer untrace("b")
fmt.Println("in b")
a()
}
func main() {
b()
}

内置函数
Go 语言拥有一些不需要进行导入操作就可以使用的内置函数。它们有时可以针对不同的类型进行操作。以下函数在以后会用到
| 名称 | 说明 |
|---|---|
| close | 用于管道通信 |
| len、cap | len 用于返回某个类型的长度或数量(字符串、数组、切片、map 和管道);cap 是容量的意思,用于返回某个类型的最大容量(只能用于切片和 map) |
| new、make | new 和 make 均是用于分配内存:new 用于值类型和用户定义的类型,如自定义结构,make 用于内置引用类型(切片、map 和管道)。它们的用法就像是函数,但是将类型作为参数:new (type)、make (type)。new (T) 分配类型 T 的零值并返回其地址,也就是指向类型 T 的指针(详见第 10.1 节)。它也可以被用于基本类型:<font style="background-color:rgba(255, 255, 255, 0);">v := new(int)</font>。make (T) 返回类型 T 的初始化之后的值,因此它比 new 进行更多的工作(详见第 7.2.3/4 节、第 8.1.1 节和第 14.2.1 节)new () 是一个函数,不要忘记它的括号 |
| copy、append | 用于复制和连接切片 |
| panic、recover | 两者均用于错误处理机制 |
| print、println | 底层打印函数(详见第 4.2 节),在部署环境中建议使用 fmt 包 |
| complex、real、imag | 用于创建和操作复数(详见第 4.5.2.2 节) |
将函数作为参数
这样的参数在C,erlang很常见,被称为callback
package main
import (
"fmt"
)
func main() {
callback(1, Add)
}
func Add(a, b int) {
fmt.Printf("The sum of %d and %d is: %d\n", a, b, a+b)
}
func callback(y int, f func(int, int)) {
f(y, 2) // this becomes Add(1, 2)
}
闭包
匿名函数同样被称之为闭包(函数式语言的术语):它们被允许调用定义在其它环境下的变量。闭包可使得某个函数捕捉到一些外部状态,例如:函数被创建时的状态。另一种表示方式为:一个闭包继承了函数所声明时的作用域。这种状态(作用域内的变量)都被共享到闭包的环境中,因此这些变量可以在闭包中被操作,直到被销毁。
闭包的作用大概是将匿名函数作为函数返回值:
package main
import "fmt"
func main() {
p2 := Add2()
fmt.Printf("Call Add2 for 3 gives: %v\n", p2(3))
TwoAdder := Adder(2)
fmt.Printf("The result is: %v\n", TwoAdder(3))
}
func Add2() func(b int) int {
return func(b int) int {
return b + 2
}
}
func Adder(a int) func(b int) int {
return func(b int) int {
return a + b
}
}
浙公网安备 33010602011771号