💜 想真正擅长编程? 从一门课程开始,100% 免费

《笔记》第十八篇 函数入参与出参及多结果输出

第18讲 函数入参与出参及多结果输出

本讲基于视频实际讲解内容整理


一、Windows智能拦截问题详解

老师在本讲开头再次详细讲解了Windows智能拦截问题:

  • 电脑系统升级后,Windows会自动开启智能拦截功能
  • 智能拦截会阻止IDE和程序正常运行
  • 很多同学以为是代码或环境的问题,实际是系统安全策略导致
  • 解决方法:在Windows安全中心中关闭智能屏幕筛选器

这与第17讲提到的是同一问题,老师再次强调是因为很多同学仍然遇到这个困扰。


二、Go的多返回值

2.1 Go vs Java

特性 Java Go
多返回值 ❌ 不支持 ✅ 支持
忽略返回值 不适用 ✅ 用 _ 忽略

Go原生支持多返回值,这是Go语言的设计特色之一,非常实用。

2.2 多返回值语法

Go
func 函数名(参数列表) (返回类型1, 返回类型2) {
    return 值1, 值2
}

2.3 示例:除法运算

Go
package main

import "fmt"

// 同时返回商和余数
func divAndMod(a int, b int) (int, int) {
    return a / b, a % b
}

func main() {
    // 接收所有返回值
    div, mod := divAndMod(17, 5)
    fmt.Println("商:", div)    // 3
    fmt.Println("余数:", mod)  // 2

    // 只接收一个返回值,用_忽略另一个
    quotient, _ := divAndMod(20, 3)
    fmt.Println("只需要商:", quotient)  // 6
}

三、下划线(_)忽略返回值

当函数有多个返回值,但只需要其中部分时,用 _ 占位:

Go
// 忽略第一个返回值
_, mod := divAndMod(17, 5)

// 忽略第二个返回值
div, _ := divAndMod(17, 5)

// 忽略所有返回值(不推荐,除非有副作用)
divAndMod(17, 5)

四、封装中的返回值约定

老师强调,在Go的封装实践中,函数通常返回两个值:

  1. 实际值(结果)
  2. error(错误信息)

这是Go语言中最常见的函数签名模式:

Go
func doSomething(params...) (result, error) {
    // 处理逻辑
    if 出错条件 {
        return nil, errors.New("错误描述")
    }
    return result, nil
}

4.1 实际示例

Go
package main

import (
    "errors"
    "fmt"
)

// 安全除法:返回商和error
func safeDiv(a int, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("除数不能为零")
    }
    return a / b, nil
}

func main() {
    result, err := safeDiv(10, 0)
    if err != nil {
        fmt.Println("出错了:", err)
        return
    }
    fmt.Println("结果:", result)
}

Go的错误处理哲学:Go不使用try-catch异常机制,而是通过返回值来传递错误。调用者必须检查error是否为nil。

4.2 忽略error的写法

Go
// 忽略error(不推荐,但语法允许)
result, _ := safeDiv(10, 2)
fmt.Println(result)

五、range 关键字遍历

老师在本讲中还介绍了 range 关键字,用于遍历数组、切片、Map等:

5.1 遍历切片/数组

Go
nums := []int{10, 20, 30, 40}

// range 返回下标和值
for index, value := range nums {
    fmt.Printf("下标: %d, 值: %d\n", index, value)
}

// 只需要值,忽略下标
for _, value := range nums {
    fmt.Println(value)
}

// 只需要下标
for index := range nums {
    fmt.Println("下标:", index)
}

5.2 遍历Map

Go
scores := map[string]int{
    "张三": 90,
    "李四": 85,
    "王五": 78,
}

for name, score := range scores {
    fmt.Printf("%s: %d分\n", name, score)
}

range 遍历Map时返回 key 和 value 两个值,同样可以用 _ 忽略不需要的值。


六、学习编程需要实际项目练习

老师在课程中分享了一段亲身经历,非常具有启发性:

老师的分享

  • 老师曾在财经大学实验室工作
  • 当时学C++,看语法觉得都会,但真正写项目时却写不出来
  • 看懂语法 ≠ 会写程序

核心观点

学习编程不能只停留在看语法、看视频的阶段。语法看懂了,不代表能写出程序。必须通过实际项目来练习,才能真正掌握编程能力。

老师建议:

  1. 学完基础语法后,要动手写真实项目
  2. 从小项目开始,逐步增加复杂度
  3. 遇到问题自己查文档、搜索解决方案
  4. 只有在实践中遇到并解决问题,才能真正理解知识点

七、本讲小结

知识点 要点
多返回值 Go支持,Java不支持
下划线 _ 忽略不需要的返回值
封装约定 通常返回 (result, error) 两个值
range关键字 遍历数组、切片、Map
range返回值 下标+值(切片/数组),key+value(Map)
错误处理 Go不使用try-catch,通过返回error处理
学习方法 必须通过实际项目练习,不能只看语法

八、课后练习

  1. 编写一个函数 swap(a, b int) (int, int),交换两个数并返回
  2. 编写一个函数 divide(a, b float64) (float64, error),当b为0时返回error
  3. 使用 range 遍历一个 []string 切片,打印每个元素的下标和值
  4. 使用 range 遍历一个 map[string]int,打印所有的key-value对
  5. 调用 divide 函数,分别处理正常和出错的情况
  6. 思考:为什么Go选择用返回值而不是try-catch来处理错误?