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
    }
}

posted on 2025-06-17 23:06  依只  阅读(15)  评论(0)    收藏  举报

导航