774 lines
18 KiB
Go
774 lines
18 KiB
Go
/*
|
||
02-multiple-returns.go - Go 语言多返回值详解
|
||
|
||
学习目标:
|
||
1. 掌握多返回值的语法和用法
|
||
2. 理解命名返回值的优势
|
||
3. 学会错误处理的惯用模式
|
||
4. 了解多返回值的实际应用场景
|
||
5. 掌握返回值的最佳实践
|
||
|
||
知识点:
|
||
- 多返回值语法
|
||
- 命名返回值
|
||
- 错误处理模式
|
||
- 返回值解构
|
||
- 忽略返回值
|
||
- 多返回值的性能考虑
|
||
- 实际应用场景
|
||
*/
|
||
|
||
package main
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"math"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
func main() {
|
||
fmt.Println("=== Go 语言多返回值详解 ===\n")
|
||
|
||
// 演示基本多返回值
|
||
demonstrateBasicMultipleReturns()
|
||
|
||
// 演示命名返回值
|
||
demonstrateNamedReturns()
|
||
|
||
// 演示错误处理模式
|
||
demonstrateErrorHandling()
|
||
|
||
// 演示返回值解构和忽略
|
||
demonstrateReturnValueHandling()
|
||
|
||
// 演示多返回值的实际应用
|
||
demonstratePracticalApplications()
|
||
|
||
// 演示多返回值的高级用法
|
||
demonstrateAdvancedUsage()
|
||
|
||
// 演示性能考虑
|
||
demonstratePerformanceConsiderations()
|
||
}
|
||
|
||
// demonstrateBasicMultipleReturns 演示基本多返回值
|
||
func demonstrateBasicMultipleReturns() {
|
||
fmt.Println("1. 基本多返回值:")
|
||
|
||
// 两个返回值
|
||
fmt.Printf(" 两个返回值:\n")
|
||
quotient, remainder := divmod(17, 5)
|
||
fmt.Printf(" 17 ÷ 5 = %d 余 %d\n", quotient, remainder)
|
||
|
||
// 三个返回值
|
||
fmt.Printf(" 三个返回值:\n")
|
||
min, max, avg := analyzeNumbers([]int{3, 7, 1, 9, 4, 6})
|
||
fmt.Printf(" 数组 [3, 7, 1, 9, 4, 6] - 最小值: %d, 最大值: %d, 平均值: %.2f\n", min, max, avg)
|
||
|
||
// 不同类型的返回值
|
||
fmt.Printf(" 不同类型的返回值:\n")
|
||
name, age, height, isStudent := getPersonInfo()
|
||
fmt.Printf(" 个人信息 - 姓名: %s, 年龄: %d, 身高: %.1fcm, 学生: %t\n",
|
||
name, age, height, isStudent)
|
||
|
||
// 返回值和错误
|
||
fmt.Printf(" 返回值和错误:\n")
|
||
result, err := safeDivide(10, 2)
|
||
if err != nil {
|
||
fmt.Printf(" 错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 10 ÷ 2 = %.2f\n", result)
|
||
}
|
||
|
||
result, err = safeDivide(10, 0)
|
||
if err != nil {
|
||
fmt.Printf(" 错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 10 ÷ 0 = %.2f\n", result)
|
||
}
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstrateNamedReturns 演示命名返回值
|
||
func demonstrateNamedReturns() {
|
||
fmt.Println("2. 命名返回值:")
|
||
|
||
// 基本命名返回值
|
||
fmt.Printf(" 基本命名返回值:\n")
|
||
area, perimeter := calculateRectangle(5, 3)
|
||
fmt.Printf(" 矩形 5×3 - 面积: %d, 周长: %d\n", area, perimeter)
|
||
|
||
// 命名返回值的提前返回
|
||
fmt.Printf(" 命名返回值的提前返回:\n")
|
||
score, grade, pass := evaluateScore(85)
|
||
fmt.Printf(" 分数 85 - 等级: %s, 是否及格: %t\n", grade, pass)
|
||
|
||
score, grade, pass = evaluateScore(45)
|
||
fmt.Printf(" 分数 45 - 等级: %s, 是否及格: %t\n", grade, pass)
|
||
|
||
// 复杂的命名返回值
|
||
fmt.Printf(" 复杂的命名返回值:\n")
|
||
valid, reason, suggestions := validatePassword("123")
|
||
fmt.Printf(" 密码 \"123\" - 有效: %t, 原因: %s\n", valid, reason)
|
||
if len(suggestions) > 0 {
|
||
fmt.Printf(" 建议: %v\n", suggestions)
|
||
}
|
||
|
||
valid, reason, suggestions = validatePassword("SecurePass123!")
|
||
fmt.Printf(" 密码 \"SecurePass123!\" - 有效: %t, 原因: %s\n", valid, reason)
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstrateErrorHandling 演示错误处理模式
|
||
func demonstrateErrorHandling() {
|
||
fmt.Println("3. 错误处理模式:")
|
||
|
||
// 标准错误处理模式
|
||
fmt.Printf(" 标准错误处理模式:\n")
|
||
|
||
// 字符串转整数
|
||
value, err := parseInteger("123")
|
||
if err != nil {
|
||
fmt.Printf(" 解析错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 解析成功: %d\n", value)
|
||
}
|
||
|
||
value, err = parseInteger("abc")
|
||
if err != nil {
|
||
fmt.Printf(" 解析错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 解析成功: %d\n", value)
|
||
}
|
||
|
||
// 文件操作模拟
|
||
fmt.Printf(" 文件操作模拟:\n")
|
||
content, err := readFile("config.txt")
|
||
if err != nil {
|
||
fmt.Printf(" 读取文件错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 文件内容: %s\n", content)
|
||
}
|
||
|
||
// 网络请求模拟
|
||
fmt.Printf(" 网络请求模拟:\n")
|
||
data, statusCode, err := httpGet("https://api.example.com/users")
|
||
if err != nil {
|
||
fmt.Printf(" 请求错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 状态码: %d, 数据长度: %d\n", statusCode, len(data))
|
||
}
|
||
|
||
// 多层错误处理
|
||
fmt.Printf(" 多层错误处理:\n")
|
||
result, err := processUserData("user123")
|
||
if err != nil {
|
||
fmt.Printf(" 处理用户数据错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 处理结果: %s\n", result)
|
||
}
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstrateReturnValueHandling 演示返回值解构和忽略
|
||
func demonstrateReturnValueHandling() {
|
||
fmt.Println("4. 返回值解构和忽略:")
|
||
|
||
// 接收所有返回值
|
||
fmt.Printf(" 接收所有返回值:\n")
|
||
x, y, z := getCoordinates()
|
||
fmt.Printf(" 坐标: (%d, %d, %d)\n", x, y, z)
|
||
|
||
// 忽略某些返回值
|
||
fmt.Printf(" 忽略某些返回值:\n")
|
||
_, _, avgZ := getCoordinates()
|
||
fmt.Printf(" 只关心 Z 坐标: %d\n", avgZ)
|
||
|
||
// 只检查错误
|
||
fmt.Printf(" 只检查错误:\n")
|
||
_, err := safeDivide(10, 2)
|
||
if err != nil {
|
||
fmt.Printf(" 操作失败: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 操作成功\n")
|
||
}
|
||
|
||
// 链式调用
|
||
fmt.Printf(" 链式调用:\n")
|
||
result, err := processChain("input")
|
||
if err != nil {
|
||
fmt.Printf(" 链式处理错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 链式处理结果: %s\n", result)
|
||
}
|
||
|
||
// 多重赋值
|
||
fmt.Printf(" 多重赋值:\n")
|
||
a, b := 10, 20
|
||
fmt.Printf(" 交换前: a=%d, b=%d\n", a, b)
|
||
a, b = swap(a, b)
|
||
fmt.Printf(" 交换后: a=%d, b=%d\n", a, b)
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstratePracticalApplications 演示多返回值的实际应用
|
||
func demonstratePracticalApplications() {
|
||
fmt.Println("5. 多返回值的实际应用:")
|
||
|
||
// 应用1: 数据库查询模拟
|
||
fmt.Printf(" 应用1 - 数据库查询模拟:\n")
|
||
user, found, err := findUserByID(123)
|
||
if err != nil {
|
||
fmt.Printf(" 查询错误: %v\n", err)
|
||
} else if !found {
|
||
fmt.Printf(" 用户不存在\n")
|
||
} else {
|
||
fmt.Printf(" 找到用户: %+v\n", user)
|
||
}
|
||
|
||
// 应用2: 缓存操作
|
||
fmt.Printf(" 应用2 - 缓存操作:\n")
|
||
value, hit, err := getFromCache("user:123")
|
||
if err != nil {
|
||
fmt.Printf(" 缓存错误: %v\n", err)
|
||
} else if hit {
|
||
fmt.Printf(" 缓存命中: %s\n", value)
|
||
} else {
|
||
fmt.Printf(" 缓存未命中\n")
|
||
}
|
||
|
||
// 应用3: 配置解析
|
||
fmt.Printf(" 应用3 - 配置解析:\n")
|
||
config, warnings, err := parseConfig("app.conf")
|
||
if err != nil {
|
||
fmt.Printf(" 配置解析错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 配置加载成功: %+v\n", config)
|
||
if len(warnings) > 0 {
|
||
fmt.Printf(" 警告: %v\n", warnings)
|
||
}
|
||
}
|
||
|
||
// 应用4: 数据验证
|
||
fmt.Printf(" 应用4 - 数据验证:\n")
|
||
userData := map[string]string{
|
||
"name": "Alice",
|
||
"email": "alice@example.com",
|
||
"age": "25",
|
||
}
|
||
|
||
valid, errors := validateUserData(userData)
|
||
fmt.Printf(" 用户数据验证 - 有效: %t\n", valid)
|
||
if len(errors) > 0 {
|
||
fmt.Printf(" 验证错误: %v\n", errors)
|
||
}
|
||
|
||
// 应用5: 统计分析
|
||
fmt.Printf(" 应用5 - 统计分析:\n")
|
||
data := []float64{1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0}
|
||
mean, median, stddev := calculateStatistics(data)
|
||
fmt.Printf(" 数据: %v\n", data)
|
||
fmt.Printf(" 统计结果 - 平均值: %.2f, 中位数: %.2f, 标准差: %.2f\n",
|
||
mean, median, stddev)
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstrateAdvancedUsage 演示多返回值的高级用法
|
||
func demonstrateAdvancedUsage() {
|
||
fmt.Println("6. 多返回值的高级用法:")
|
||
|
||
// 返回函数
|
||
fmt.Printf(" 返回函数:\n")
|
||
add, multiply := getMathOperations()
|
||
fmt.Printf(" add(5, 3) = %d\n", add(5, 3))
|
||
fmt.Printf(" multiply(5, 3) = %d\n", multiply(5, 3))
|
||
|
||
// 返回接口
|
||
fmt.Printf(" 返回接口:\n")
|
||
reader, writer := getIOOperations()
|
||
data := []byte("Hello, World!")
|
||
|
||
n, err := writer.Write(data)
|
||
if err != nil {
|
||
fmt.Printf(" 写入错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 写入 %d 字节\n", n)
|
||
}
|
||
|
||
buffer := make([]byte, 13)
|
||
n, err = reader.Read(buffer)
|
||
if err != nil {
|
||
fmt.Printf(" 读取错误: %v\n", err)
|
||
} else {
|
||
fmt.Printf(" 读取 %d 字节: %s\n", n, string(buffer[:n]))
|
||
}
|
||
|
||
// 返回通道
|
||
fmt.Printf(" 返回通道:\n")
|
||
input, output := createPipeline()
|
||
|
||
// 发送数据
|
||
go func() {
|
||
for i := 1; i <= 3; i++ {
|
||
input <- i
|
||
}
|
||
close(input)
|
||
}()
|
||
|
||
// 接收处理后的数据
|
||
for result := range output {
|
||
fmt.Printf(" 处理结果: %d\n", result)
|
||
}
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// demonstratePerformanceConsiderations 演示性能考虑
|
||
func demonstratePerformanceConsiderations() {
|
||
fmt.Println("7. 性能考虑:")
|
||
|
||
// 返回值的内存分配
|
||
fmt.Printf(" 返回值的内存分配:\n")
|
||
|
||
// 返回值拷贝 vs 返回指针
|
||
largeData := make([]int, 1000)
|
||
for i := range largeData {
|
||
largeData[i] = i
|
||
}
|
||
|
||
// 返回拷贝(可能影响性能)
|
||
copied, size := copyLargeData(largeData)
|
||
fmt.Printf(" 返回拷贝 - 大小: %d, 第一个元素: %d\n", size, copied[0])
|
||
|
||
// 返回指针(更高效)
|
||
ptr, size := referenceLargeData(largeData)
|
||
fmt.Printf(" 返回指针 - 大小: %d, 第一个元素: %d\n", size, (*ptr)[0])
|
||
|
||
// 多返回值 vs 结构体
|
||
fmt.Printf(" 多返回值 vs 结构体:\n")
|
||
|
||
// 使用多返回值
|
||
name, age, email := getUserInfo1()
|
||
fmt.Printf(" 多返回值: %s, %d, %s\n", name, age, email)
|
||
|
||
// 使用结构体
|
||
user := getUserInfo2()
|
||
fmt.Printf(" 结构体: %s, %d, %s\n", user.Name, user.Age, user.Email)
|
||
|
||
// 错误处理的性能
|
||
fmt.Printf(" 错误处理的性能:\n")
|
||
|
||
// 正常情况
|
||
start := time.Now()
|
||
for i := 0; i < 1000; i++ {
|
||
_, err := fastOperation(i)
|
||
if err != nil {
|
||
// 处理错误
|
||
}
|
||
}
|
||
duration := time.Since(start)
|
||
fmt.Printf(" 1000次正常操作耗时: %v\n", duration)
|
||
|
||
fmt.Println()
|
||
}
|
||
|
||
// ========== 函数定义 ==========
|
||
|
||
// 基本多返回值函数
|
||
func divmod(a, b int) (int, int) {
|
||
return a / b, a % b
|
||
}
|
||
|
||
func analyzeNumbers(numbers []int) (int, int, float64) {
|
||
if len(numbers) == 0 {
|
||
return 0, 0, 0
|
||
}
|
||
|
||
min, max := numbers[0], numbers[0]
|
||
sum := 0
|
||
|
||
for _, num := range numbers {
|
||
if num < min {
|
||
min = num
|
||
}
|
||
if num > max {
|
||
max = num
|
||
}
|
||
sum += num
|
||
}
|
||
|
||
avg := float64(sum) / float64(len(numbers))
|
||
return min, max, avg
|
||
}
|
||
|
||
func getPersonInfo() (string, int, float64, bool) {
|
||
return "Alice", 25, 165.5, true
|
||
}
|
||
|
||
func safeDivide(a, b float64) (float64, error) {
|
||
if b == 0 {
|
||
return 0, errors.New("除数不能为零")
|
||
}
|
||
return a / b, nil
|
||
}
|
||
|
||
// 命名返回值函数
|
||
func calculateRectangle(width, height int) (area, perimeter int) {
|
||
area = width * height
|
||
perimeter = 2 * (width + height)
|
||
return // 自动返回命名的返回值
|
||
}
|
||
|
||
func evaluateScore(score int) (originalScore int, grade string, pass bool) {
|
||
originalScore = score
|
||
|
||
if score < 0 || score > 100 {
|
||
grade = "无效"
|
||
return // 提前返回
|
||
}
|
||
|
||
switch {
|
||
case score >= 90:
|
||
grade = "A"
|
||
case score >= 80:
|
||
grade = "B"
|
||
case score >= 70:
|
||
grade = "C"
|
||
case score >= 60:
|
||
grade = "D"
|
||
default:
|
||
grade = "F"
|
||
}
|
||
|
||
pass = score >= 60
|
||
return
|
||
}
|
||
|
||
func validatePassword(password string) (valid bool, reason string, suggestions []string) {
|
||
if len(password) < 8 {
|
||
reason = "密码长度不足8位"
|
||
suggestions = append(suggestions, "增加密码长度")
|
||
return
|
||
}
|
||
|
||
hasUpper := strings.ContainsAny(password, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||
hasLower := strings.ContainsAny(password, "abcdefghijklmnopqrstuvwxyz")
|
||
hasDigit := strings.ContainsAny(password, "0123456789")
|
||
hasSpecial := strings.ContainsAny(password, "!@#$%^&*")
|
||
|
||
if !hasUpper {
|
||
suggestions = append(suggestions, "添加大写字母")
|
||
}
|
||
if !hasLower {
|
||
suggestions = append(suggestions, "添加小写字母")
|
||
}
|
||
if !hasDigit {
|
||
suggestions = append(suggestions, "添加数字")
|
||
}
|
||
if !hasSpecial {
|
||
suggestions = append(suggestions, "添加特殊字符")
|
||
}
|
||
|
||
if hasUpper && hasLower && hasDigit && hasSpecial {
|
||
valid = true
|
||
reason = "密码强度良好"
|
||
} else {
|
||
reason = "密码强度不足"
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
// 错误处理函数
|
||
func parseInteger(s string) (int, error) {
|
||
value, err := strconv.Atoi(s)
|
||
if err != nil {
|
||
return 0, fmt.Errorf("无法解析整数 '%s': %w", s, err)
|
||
}
|
||
return value, nil
|
||
}
|
||
|
||
func readFile(filename string) (string, error) {
|
||
// 模拟文件读取
|
||
if filename == "config.txt" {
|
||
return "server_port=8080\ndebug=true", nil
|
||
}
|
||
return "", fmt.Errorf("文件 '%s' 不存在", filename)
|
||
}
|
||
|
||
func httpGet(url string) ([]byte, int, error) {
|
||
// 模拟HTTP请求
|
||
if strings.Contains(url, "example.com") {
|
||
return []byte(`{"users": [{"id": 1, "name": "Alice"}]}`), 200, nil
|
||
}
|
||
return nil, 0, errors.New("网络连接失败")
|
||
}
|
||
|
||
func processUserData(userID string) (string, error) {
|
||
// 模拟多层处理
|
||
if userID == "" {
|
||
return "", errors.New("用户ID不能为空")
|
||
}
|
||
|
||
// 模拟数据库查询
|
||
if userID == "user123" {
|
||
return "用户数据处理完成", nil
|
||
}
|
||
|
||
return "", fmt.Errorf("用户 '%s' 不存在", userID)
|
||
}
|
||
|
||
// 返回值处理函数
|
||
func getCoordinates() (int, int, int) {
|
||
return 10, 20, 30
|
||
}
|
||
|
||
func processChain(input string) (string, error) {
|
||
if input == "" {
|
||
return "", errors.New("输入不能为空")
|
||
}
|
||
|
||
// 模拟处理链
|
||
step1 := strings.ToUpper(input)
|
||
step2 := step1 + "_PROCESSED"
|
||
|
||
return step2, nil
|
||
}
|
||
|
||
func swap(a, b int) (int, int) {
|
||
return b, a
|
||
}
|
||
|
||
// 实际应用函数
|
||
type User struct {
|
||
ID int
|
||
Name string
|
||
Email string
|
||
}
|
||
|
||
func findUserByID(id int) (User, bool, error) {
|
||
// 模拟数据库查询
|
||
if id <= 0 {
|
||
return User{}, false, errors.New("无效的用户ID")
|
||
}
|
||
|
||
if id == 123 {
|
||
return User{ID: 123, Name: "Alice", Email: "alice@example.com"}, true, nil
|
||
}
|
||
|
||
return User{}, false, nil
|
||
}
|
||
|
||
func getFromCache(key string) (string, bool, error) {
|
||
// 模拟缓存操作
|
||
cache := map[string]string{
|
||
"user:123": "Alice",
|
||
"user:456": "Bob",
|
||
}
|
||
|
||
if value, exists := cache[key]; exists {
|
||
return value, true, nil
|
||
}
|
||
|
||
return "", false, nil
|
||
}
|
||
|
||
type Config struct {
|
||
Port int
|
||
Debug bool
|
||
Timeout int
|
||
}
|
||
|
||
func parseConfig(filename string) (Config, []string, error) {
|
||
// 模拟配置解析
|
||
config := Config{Port: 8080, Debug: true, Timeout: 30}
|
||
warnings := []string{"使用默认超时值"}
|
||
|
||
if filename == "app.conf" {
|
||
return config, warnings, nil
|
||
}
|
||
|
||
return Config{}, nil, fmt.Errorf("配置文件 '%s' 不存在", filename)
|
||
}
|
||
|
||
func validateUserData(data map[string]string) (bool, []string) {
|
||
var errors []string
|
||
|
||
if name := data["name"]; name == "" {
|
||
errors = append(errors, "姓名不能为空")
|
||
}
|
||
|
||
if email := data["email"]; !strings.Contains(email, "@") {
|
||
errors = append(errors, "邮箱格式无效")
|
||
}
|
||
|
||
if ageStr := data["age"]; ageStr != "" {
|
||
if age, err := strconv.Atoi(ageStr); err != nil || age < 0 || age > 150 {
|
||
errors = append(errors, "年龄无效")
|
||
}
|
||
}
|
||
|
||
return len(errors) == 0, errors
|
||
}
|
||
|
||
func calculateStatistics(data []float64) (mean, median, stddev float64) {
|
||
if len(data) == 0 {
|
||
return 0, 0, 0
|
||
}
|
||
|
||
// 计算平均值
|
||
sum := 0.0
|
||
for _, v := range data {
|
||
sum += v
|
||
}
|
||
mean = sum / float64(len(data))
|
||
|
||
// 计算中位数(简化版)
|
||
median = data[len(data)/2]
|
||
|
||
// 计算标准差
|
||
variance := 0.0
|
||
for _, v := range data {
|
||
variance += (v - mean) * (v - mean)
|
||
}
|
||
stddev = math.Sqrt(variance / float64(len(data)))
|
||
|
||
return
|
||
}
|
||
|
||
// 高级用法函数
|
||
func getMathOperations() (func(int, int) int, func(int, int) int) {
|
||
add := func(a, b int) int { return a + b }
|
||
multiply := func(a, b int) int { return a * b }
|
||
return add, multiply
|
||
}
|
||
|
||
type MockReader struct {
|
||
data []byte
|
||
pos int
|
||
}
|
||
|
||
func (r *MockReader) Read(p []byte) (n int, error) {
|
||
if r.pos >= len(r.data) {
|
||
return 0, errors.New("EOF")
|
||
}
|
||
|
||
n = copy(p, r.data[r.pos:])
|
||
r.pos += n
|
||
return n, nil
|
||
}
|
||
|
||
type MockWriter struct {
|
||
data []byte
|
||
}
|
||
|
||
func (w *MockWriter) Write(p []byte) (n int, error) {
|
||
w.data = append(w.data, p...)
|
||
return len(p), nil
|
||
}
|
||
|
||
func getIOOperations() (*MockReader, *MockWriter) {
|
||
reader := &MockReader{data: []byte("Hello, World!")}
|
||
writer := &MockWriter{}
|
||
return reader, writer
|
||
}
|
||
|
||
func createPipeline() (chan<- int, <-chan int) {
|
||
input := make(chan int)
|
||
output := make(chan int)
|
||
|
||
go func() {
|
||
defer close(output)
|
||
for value := range input {
|
||
output <- value * 2 // 处理数据
|
||
}
|
||
}()
|
||
|
||
return input, output
|
||
}
|
||
|
||
// 性能考虑函数
|
||
func copyLargeData(data []int) ([]int, int) {
|
||
copied := make([]int, len(data))
|
||
copy(copied, data)
|
||
return copied, len(copied)
|
||
}
|
||
|
||
func referenceLargeData(data []int) (*[]int, int) {
|
||
return &data, len(data)
|
||
}
|
||
|
||
func getUserInfo1() (string, int, string) {
|
||
return "Alice", 25, "alice@example.com"
|
||
}
|
||
|
||
type UserInfo struct {
|
||
Name string
|
||
Age int
|
||
Email string
|
||
}
|
||
|
||
func getUserInfo2() UserInfo {
|
||
return UserInfo{Name: "Alice", Age: 25, Email: "alice@example.com"}
|
||
}
|
||
|
||
func fastOperation(n int) (int, error) {
|
||
if n < 0 {
|
||
return 0, errors.New("负数")
|
||
}
|
||
return n * 2, nil
|
||
}
|
||
|
||
/*
|
||
运行这个程序:
|
||
go run 02-multiple-returns.go
|
||
|
||
学习要点:
|
||
1. Go 支持多返回值,这是其独特且强大的特性
|
||
2. 多返回值常用于返回结果和错误信息
|
||
3. 命名返回值可以提高代码可读性,支持提前返回
|
||
4. 可以使用 _ 忽略不需要的返回值
|
||
5. 多返回值是 Go 错误处理的基础
|
||
|
||
多返回值的优势:
|
||
1. 避免使用指针参数传递多个结果
|
||
2. 使错误处理更加明确和一致
|
||
3. 提高代码的可读性和维护性
|
||
4. 支持函数式编程风格
|
||
|
||
常见模式:
|
||
1. (result, error) - 标准错误处理模式
|
||
2. (value, ok) - 检查操作是否成功
|
||
3. (value, found, error) - 查询操作模式
|
||
4. 命名返回值 - 提高可读性
|
||
|
||
最佳实践:
|
||
1. 错误通常作为最后一个返回值
|
||
2. 使用命名返回值提高复杂函数的可读性
|
||
3. 适当使用 _ 忽略不需要的返回值
|
||
4. 保持返回值数量合理(通常不超过3-4个)
|
||
5. 考虑使用结构体替代过多的返回值
|
||
|
||
性能考虑:
|
||
1. 多返回值通常比传递指针参数更高效
|
||
2. 大对象考虑返回指针而不是值拷贝
|
||
3. 命名返回值可能有轻微的性能开销
|
||
4. 错误处理的性能影响通常可以忽略
|
||
|
||
应用场景:
|
||
1. 错误处理
|
||
2. 数据库查询
|
||
3. 网络操作
|
||
4. 文件操作
|
||
5. 数据验证
|
||
6. 统计计算
|
||
7. 缓存操作
|
||
*/ |