Go小白入门6 - 函数

1. 函数的定义

  • 当参数类型相同时,可以省略掉前面的类型
  • 想传递给函数的参数不能确定有多少时,可使用变长参数 => 变长参数必须放在函数参数的最后
func function_name([parameter list]) [return _types]{
	// 函数体
}

1.1 简单栗子 - max()函数

package main

import "fmt"

func main() {
	fmt.Println(max(2, 3))
}

func max(num1, num2 int) int {
	if num1 > num2 {
		return num1
	}
	return num2
}

1.2 多返回值

通过返回结果与一个错误值,可以使函数调用者知道函数是否执行成功,这也称为command,ok模式(推荐)

package main

import (
	"errors"
	"fmt"
)

func main() {
	result, err := div(1, 2)
	if err != nil {
		fmt.Printf("error: %v", err)
		return
	}
	fmt.Println("result: ", result)
}

func div(a, b float64) (float64, error) {
	if b == 0 {
		return 0, errors.New("the divisor cannot be zero")
	}
	return a / b, nil
}

1.3 给返回值命名

需要返回的时候,我们只需要一条简单的不带参数的return语句

func div(a, b float64) (result float64, err error) {
	if b == 0 {
		return 0, errors.New("被除数不能等于0")
	}
	result = a / b
	return
}

2. 函数的参数和调用

形参就像定义在函数体内的局部变量

调用函数,可通过两种方式来传递参数:

  • 值传递:将实际参数复制一份传递到函数中 => 在函数中修改参数,不会影响实际参数
  • 引用传递:将实际参数的地址传递到函数中 => 修改参数,会影响实际参数

默认情况下,Go 语言使用值传递。

package main
import "fmt"

func main() {
	a := 1
	b := 1
	c := []int{1, 2, 3}
	paramFunc(a, &b, c)

	fmt.Println("main:")
	fmt.Println(a) // 未变
	fmt.Println(b) // 变了
	fmt.Println(c) // 变了
}

func paramFunc(a int, b *int, c []int) {
	a = 100
	*b = 100
	c[1] = 100

	fmt.Println("paramFunc:")
	fmt.Println(a)
	fmt.Println(*b)
	fmt.Println(c)
}

3. 函数的用法

3.1 函数的作为实参

函数定义后可作为另外一个函数的实参数传入

1)该函数仅是为了使用内置函数math.sqrt()

package main

import (
	"fmt"
	"math"
)

func main() {
	getSquareRoot := func(x float64) float64 {
		return math.Sqrt(x)
	}

	fmt.Println(getSquareRoot(9))
}

2)函数作为参数传递,实现回调

package main

import (
	"fmt"
)

func main() {
	callBack0(1, callBack)
	callBack0(2, func(x int) int {
		fmt.Printf("I'm callback:%d\n", x)
		return x
	})

}

type cb func(int) int

func callBack0(x int, f cb) {
	f(x)
}

func callBack(x int) int {
	fmt.Printf("I'm callback:%d\n", x)
	return x
}

3.2 闭包

Go 支持匿名函数,可作为闭包(匿名函数可直接使用函数内的变量,不必申明)

  • 闭包:一个函数与这个函数外部变量的一个封装
  • 闭包:一个类 - 类里有变量和方法,其中闭包所包含的外部变量对应着类中的静态变量
  • 闭包通过操作指针来调用对应的变量
package main

import "fmt"

func main() {
	nextNumber := getSequence() // nextNumber为一个函数 - i=0
	fmt.Println(nextNumber())   //1
	fmt.Println(nextNumber())   //2
	fmt.Println(nextNumber())   //3

	nextNumber1 := getSequence()
	fmt.Println(nextNumber1()) //1
	fmt.Println(nextNumber1()) //2
}

func getSequence() func() int {
	i := 0
	return func() int {
		i++
		return i
	}
}

带参数的闭包

package main

import "fmt"

func main() {
	addFunc := add(1, 2)
	fmt.Println(addFunc()) //1 3
	fmt.Println(addFunc()) //2 3
	fmt.Println(addFunc()) //3 3
}

func add(x, y int) func() (int, int) {
	i := 0
	return func() (int, int) {
		i++
		return i, x + y
	}
}

3.3 函数方法

package main

import "fmt"

// Circle - define structure
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
}

4. 小练习

4.1 栗子 - 值传递

在函数中修改参数,不会影响实际参数

package main

import "fmt"

func main() {
	x := 100
	y := 200
	z := swap(x, y)

	// 100, 100, 200
	fmt.Printf("z的值为:%d; 交换后的x:%d; 交换后的y:%d", z, x, y)
}

func swap(x, y int) int {
	temp := x
	x = y
	y = temp

	return temp
}

4.2 栗子 - 引用传递

在函数中修改参数,会影响实际参数

&x 指向 x 指针,x 变量的地址

package main

import "fmt"

func main() {
	x := 100
	y := 200
	swap(&x, &y)

	// 200, 100
	fmt.Printf("交换后的x:%d; 交换后的y:%d", x, y)
}

func swap(x *int, y *int) {
	*x, *y = *y, *x
}

4.3 函数返回多个值

package main

import "fmt"

func main() {
	fmt.Println(swap("haha1", "haha2"))
}

func swap(x, y string) (string, string) {
	return y, x
}

4.4 闭包实现斐波那契

package main
import "fmt"

func main() {
	f := fibonacci()
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
}

func fibonacci() func() int {
	x, y := 0, 1
	return func() int {
		x, y = y, x+y
		return x
	}
}

5. 参考资料

  1. Go菜鸟教程
  2. Datawhale组队学习
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值