package main
import (
"fmt"
"errors"
)
// 定义用户结构体
type User struct {
Username string
Age int
Email string
}
// 定义错误类型
var (
ErrDBConnection = errors.New("数据库连接错误")
ErrCacheMiss = errors.New("缓存未命中错误")
)
// 根据用户ID获取用户详细信息的函数
func GetUserByID(userID int) (User, error) {
// 模拟从缓存获取数据
user, ok := getFromCache(userID)
if ok {
return user, nil
}
// 缓存未命中,从数据库获取数据
user, err := getFromDB(userID)
if err != nil {
return User{}, ErrDBConnection
}
// 将获取到的数据存入缓存
setToCache(userID, user)
return user, nil
}
// 模拟从缓存获取数据的函数
func getFromCache(userID int) (User, bool) {
// 这里应该实现实际的缓存获取逻辑,这里简单模拟
cache := map[int]User{
1: {Username: "user1", Age: 20, Email: "user1@example.com"},
}
user, ok := cache[userID]
return user, ok
}
// 模拟从数据库获取数据的函数
func getFromDB(userID int) (User, error) {
// 这里应该实现实际的数据库查询逻辑,这里简单模拟
if userID == 1 {
return User{Username: "user1", Age: 20, Email: "user1@example.com"}, nil
}
return User{}, fmt.Errorf("数据库中未找到该用户")
}
// 模拟将数据存入缓存的函数
func setToCache(userID int, user User) {
// 这里应该实现实际的缓存设置逻辑,这里简单模拟
fmt.Printf("将用户 %d 存入缓存\n", userID)
}
多值返回提高代码可读性和可维护性的说明:
- 明确返回值:通过多值返回,函数可以同时返回用户信息和错误信息。这使得调用者能够清晰地知道函数的执行结果,无需额外的变量来存储状态。例如:
user, err := GetUserByID(1)
if err != nil {
fmt.Println("获取用户信息失败:", err)
return
}
fmt.Printf("用户名: %s, 年龄: %d, 邮箱: %s\n", user.Username, user.Age, user.Email)
- 错误处理清晰:每个错误类型都被明确定义(如
ErrDBConnection
和 ErrCacheMiss
),调用者可以根据具体的错误类型进行不同的处理。这种方式使得代码逻辑更加清晰,易于维护。
- 代码简洁:多值返回避免了使用全局变量或复杂的结构体来传递函数执行结果和错误信息,使函数接口更加简洁明了,代码整体结构更加清晰。
处理不同类型错误:
- 定义错误类型:通过
errors.New
定义不同类型的错误,如 ErrDBConnection
和 ErrCacheMiss
,使得错误类型更加明确。
- 返回错误:在函数内部,当遇到相应的错误情况时,返回对应的错误类型。例如在
getFromDB
函数中如果数据库查询失败返回 ErrDBConnection
。
- 调用者处理:调用者通过检查返回的错误值,使用
if err != nil
判断是否发生错误,并根据具体的错误类型进行相应处理。如上述示例中,调用者根据 err
决定是否输出错误信息。