Menu
CoddyTech

error 接口

本课属于 Coddy GO 学习旅程的“面向对象编程”单元。第 52 课,共 107 课。

在 Go 中,错误通过一个名为 error 的内置接口来处理。这个接口非常简单,只要求实现一个方法:

type error interface {
    Error() string
}

任何实现了返回字符串的 Error() 方法的类型,都会自动满足 error 接口。这就是 Go 的接口系统在发挥作用:无需显式声明。

创建错误最常见的方法是使用 errors 包:

import "errors"

func Divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("cannot divide by zero")
    }
    return a / b, nil
}

Go 函数通常会将错误作为最后一个返回值。没有发生错误时,返回 nil。调用方会先检查错误是否非 nil,然后再继续:

result, err := Divide(10, 0)
if err != nil {
    fmt.Println("Error:", err.Error())
    return
}
fmt.Println("Result:", result)

你也可以使用 fmt.Errorf 创建格式化的错误消息:

func GetUser(id int) (string, error) {
    if id <= 0 {
        return "", fmt.Errorf("invalid user id: %d", id)
    }
    return "Alice", nil
}

这种返回错误而不是抛出异常的模式是 Go 的基础。它让错误处理变得明确,并促使你考虑出错时会发生什么,这是编写健壮的面向对象代码的关键。

challenge icon

挑战

简单

让我们构建一个银行账户系统,展示 Go 的错误处理模式。你将创建一个简单的账户,用于验证操作,并在出错时返回有意义的错误。

你将把代码分成两个文件:

  • account.go:创建一个 BankAccount 结构体,包含一个已导出的 Owner 字段(string)和一个未导出的 balance 字段(float64)。实现以下内容:
    • NewBankAccount(owner string, initialDeposit float64) (*BankAccount, error):一个构造函数。如果初始存款为零或负数,则返回错误,错误消息为 "initial deposit must be positive"。否则,创建并返回账户。
    • Deposit(amount float64) error:向余额中存入金额。如果金额为零或负数,则返回错误,错误消息为 "deposit amount must be positive"。
    • Withdraw(amount float64) error:从余额中取出金额。如果金额为零或负数,则返回错误,错误消息为 "withdrawal amount must be positive";如果余额小于取款金额,则返回 "insufficient funds"。
    • Balance() float64:返回当前余额。
  • main.go:从输入中读取账户详情和交易金额。尝试创建账户并执行操作。每次操作后,打印成功消息或错误消息。

将提供以下输入:

  • 第 1 行:账户所有者姓名
  • 第 2 行:初始存款金额
  • 第 3 行:存款金额
  • 第 4 行:取款金额

对于每项操作,打印结果:

  • 创建账户后:Account created for [Owner] with balance: $[balance] 或 Error: [error message]
  • 存款后:Deposited successfully. New balance: $[balance] 或 Error: [error message]
  • 取款后:Withdrew successfully. New balance: $[balance] 或 Error: [error message]

所有余额值都保留两位小数。如果创建账户失败,则跳过剩余操作。

例如,输入 Alice、100、50 和 200 时,输出应为:

Account created for Alice with balance: $100.00
Deposited successfully. New balance: $150.00
Error: insufficient funds

输入 Bob、-50、25 和 10 时,输出应为:

Error: initial deposit must be positive

亲手试试

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// 读取账户持有人姓名
	ownerName, _ := reader.ReadString('\n')
	ownerName = strings.TrimSpace(ownerName)

	// 读取初始存款
	initialDepositStr, _ := reader.ReadString('\n')
	initialDeposit, _ := strconv.ParseFloat(strings.TrimSpace(initialDepositStr), 64)

	// 读取存款金额
	depositStr, _ := reader.ReadString('\n')
	depositAmount, _ := strconv.ParseFloat(strings.TrimSpace(depositStr), 64)

	// 读取取款金额
	withdrawStr, _ := reader.ReadString('\n')
	withdrawAmount, _ := strconv.ParseFloat(strings.TrimSpace(withdrawStr), 64)

	// TODO: 使用 NewBankAccount 创建一个新银行账户
	// 如果出错,打印 "Error: [error message]" 并返回
	// 如果成功,打印 "Account created for [Owner] with balance: $[balance]"

	// TODO: 尝试存入指定金额
	// 如果出错,打印 "Error: [error message]"
	// 如果成功,打印 "Deposited successfully. New balance: $[balance]"

	// TODO: 尝试取出指定金额
	// 如果出错,打印 "Error: [error message]"
	// 如果成功,打印 "Withdrew successfully. New balance: $[balance]"

	// 记得使用 fmt.Printf("%.2f", balance) 将余额格式化为保留两位小数

	_ = ownerName
	_ = initialDeposit
	_ = depositAmount
	_ = withdrawAmount
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Go 在线编译器