Go 函数的返回值

193 阅读3分钟

「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」。

什么是函数的返回值

  • 一个函数被调用后,返回给调用处的执行结果,叫做函数的返回值。
  • 调用处需要使用变量接收该结果

没有返回值

🌰

package main

import "fmt"

func hello(name string) {
	fmt.Println(name)
}

func main() {
    hello("小菠萝")
}

运行结果

小菠萝

单个返回值

🌰

package main

import "fmt"

func add(x int, y int) int {
	return x + y
}

func main() {
	fmt.Println(add(42, 13))
}

运行结果

55

多个返回值

函数可以返回任意数量的返回值,但是需要括号括起来

🌰

package main

import "fmt"

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

func main() {
	a, b := swap("hello", "world")
	fmt.Println(a, b)
}

运行结果

world hello

第二个 🌰

package main

import (
	"errors"
	"fmt"
)

func HelloError(name string) (string, error) {
	// (string,err)返回了两个值,一个 string,一个 err 类型

	// 如果 name 为空则进行错误处理
	if name == "" {
		// 返回错误,包含自定义错误信息
		return "", errors.New("empty name")
	}

	// 声明和初始化变量的快捷方式
	message := fmt.Sprintf("Hi, %v. Welcome!", name)

	// 第二个值是 nil,意味着没有错误;作为成功返回的第二个值,意味着调用者可以看到函数是成功的
	return message, nil
}
func main() {
    msg, err := HelloError("小菠萝")
	fmt.Println(msg)
	
	msg, err = HelloError("")
    // 如果 err 不为 nil 证明有错误,抛出错误信息并终止程序运行
	if err != nil {
		panic(err)
	}
	fmt.Println(msg)
}

运行结果

Hi, 小菠萝. Welcome!
panic: empty name

goroutine 1 [running]:
main.main()
	/tmp/sandbox1732163564/prog.go:28 +0xca

最常用返回多个值的场景

许多 Go 内建函数都会返回两个值,第一个是正常的值,第二个就是错误信息;然后调用者根据错误信息是否为 nil 来判断函数是否执行成功

package main

import (
	"fmt"
)

// 返回值有两个,第一个是正常的值,第二个是错误信息
func operation(a, b int, op string) (int, error) {
	switch op {
	case "+":
		return a + b, nil
	case "-":
		return a - b, nil
	case "*":
		return a * b, nil
	case "/":
		return a / b, nil
	default:
		return 0, fmt.Errorf("unsupported operation:%s", op)
	}
}

func main() {

	// 如果错误信息不为空则处理错误
	if res, err := operation(1, 2, "+"); err != nil {
		panic(err)
	} else {
		// 否则打印正常结果
		fmt.Println(res)
	}
}

运行结果

3

命名返回值

  • Go 的返回值可被命名,它们会被视作定义在函数体顶部的变量
  • 返回值的名称应当具有一定的意义,它可以作为文档使用
  • 若 return 语句没有跟参数,则直接返回已命名的返回值
  • 直接返回语句应当仅用在下面这样的短函数中,在长的函数中它们会影响代码的可读性
package main

import "fmt"

func split(sum int) (x, y int) {
    // x, y 无需再声明,可以直接赋值
	x = sum * 4 / 9
	y = sum - x
    
    // 没有跟参数,所以直接返回 x、y 变量
	return
}

func main() {
	fmt.Println(split(17))
}

运行结果

7 10

注意

虽然命名了返回值,但最后返回的变量名不一样也不会报错

package main

import "fmt"

func split(sum int) (x, y int) {
	a := sum * 4 / 9
	b := sum - a

	// 仍然返回两个 int, 但不是 x, y 变量
	return a, b
}

func main() {
	fmt.Println(split(17))
}

运行结果

7 10

空白标识符

  • _是Go中的空白标识符
  • 它可以代替任何类型的任何值

🌰

函数返回两个值,如果只要其中一个值,那另一个值可以用_代替

package main

import (
	"fmt"
)

func rectProps(length, width float64) (float64, float64) {
	var area = length * width
	var perimeter = (length + width) * 2
	return area, perimeter
}
func main() {
    // 返回的第二个值用 _ 
	area, _ := rectProps(10.8, 5.6) // perimeter is discarded
	fmt.Printf("Area %f ", area)
}

运行结果

Area 60.480000