【go语言规范】关于setter和 getter

由于标准库实现了可以直接访问某些字段的结构体(和c一样)所以go 不需要java一样的 采用大量的getter 和 setter

这一点确实很有意思,也很容易让从Java转过来的人采取反模式

(以下内容来自Claude 和 书籍《go语言经典错误100例》

在结构体中,可以用首字母小写:包私有

首字母大写, 可导出

在 Go 语言中,getter 和 setter 的使用有一些特殊的约定和考虑。让我详细分析:

Go 语言中 Getter/Setter 的命名约定

go 复制代码
type User struct {
    name string    // 小写,包私有
    Age  int      // 大写,可导出
}

// Getter - 不需要 Get 前缀
func (u *User) Name() string {
    return u.name
}

// Setter - 通常使用 Set 前缀
func (u *User) SetName(name string) {
    u.name = name
}

优点

  1. 封装性

    • 保护内部状态
    • 控制数据访问
    • 可以添加验证逻辑
  2. 灵活性

    go 复制代码
    type Circle struct {
        radius float64
    }
    
    // 可以在 getter 中添加计算逻辑
    func (c *Circle) Area() float64 {
        return math.Pi * c.radius * c.radius
    }
  3. 向后兼容------调试更容易

    go 复制代码
    type User struct {
        firstName string
        lastName  string
    }
    
    // 可以改变内部实现而不影响外部调用
    func (u *User) Name() string {
        return u.firstName + " " + u.lastName
    }

缺点

  1. 代码冗余

    go 复制代码
    type Person struct {
        Name string  // 公开字段
    }
    
    // 如果字段已经是公开的,getter/setter 可能显得多余
    func (p *Person) Name() string { return p.Name }
    func (p *Person) SetName(name string) { p.Name = name }
  2. 性能开销

    • 方法调用比直接字段访问有更多开销
    • 在性能关键场景可能需要考虑
  3. 可能过度使用

    go 复制代码
    // 不推荐
    type Config struct {
        Port int
    }
    
    func (c *Config) GetPort() int { return c.Port }
    func (c *Config) SetPort(port int) { c.Port = port }

最佳实践

  1. 选择性使用

    go 复制代码
    type User struct {
        name    string // 需要控制访问的私有字段
        Profile string // 可以直接访问的公开字段
    }
    
    // 只为确实需要的字段提供 getter/setter
    func (u *User) Name() string { return u.name }
    func (u *User) SetName(name string) error {
        if name == "" {
            return errors.New("name cannot be empty")
        }
        u.name = name
        return nil
    }
  2. 添加业务逻辑

    go 复制代码
    type Account struct {
        balance float64
    }
    
    func (a *Account) Balance() float64 {
        return a.balance
    }
    
    func (a *Account) SetBalance(amount float64) error {
        if amount < 0 {
            return errors.New("balance cannot be negative")
        }
        a.balance = amount
        return nil
    }
  3. 使用接口定义行为

    go 复制代码
    type Reader interface {
        Read() string
    }
    
    type Writer interface {
        Write(data string) error
    }

使用建议

  1. 不要盲目添加

    • 只在真正需要时才添加 getter/setter
    • 如果字段可以公开,直接使用公开字段
  2. 注重实用性

    • 添加有意义的验证逻辑
    • 考虑并发安全性
  3. 保持简单

    • 避免过度设计
    • 遵循 Go 的简洁原则
  4. 考虑性能影响

    • 在性能敏感的场景权衡使用

记住:Go 不是传统的面向对象语言,不需要为每个字段都创建 getter/setter。应该根据实际需求选择性使用。

相关推荐
Rebecca_aLi1 分钟前
码匠教育:零基础学 Python,标识符到循环全套基础语法解析
开发语言·python·正则表达式
IvanCodes8 分钟前
Python 正则表达式(十四):文本匹配、查找与替换
开发语言·python·正则表达式
夜雪一千9 分钟前
Python URL编码踩坑:单层编码、双重编码实战解析
开发语言·python
孙启超13 分钟前
【AI开发之Rust】第 21 课:双端集成与出包 —— Android(.so→AAR)与 iOS(xcframework)
开发语言·后端·rust
Brilliantwxx23 分钟前
【STM32】 __weak 弱引用、中断标志位、异常处理与 HAL_Delay 优先级
开发语言·stm32·单片机·嵌入式硬件
驭渊的小故事24 分钟前
SpringBoot 配置文件详解:properties 与 yml 从入门到实战
java·开发语言·笔记
郝学胜-神的一滴39 分钟前
游戏引擎原理与实践 02:揭开3A游戏背后的技术面纱
开发语言·计算机网络·程序人生·游戏·游戏引擎
m0_380743871 小时前
Qt实现调用相机进行拍照并进行图像处理
开发语言·c++
wangqiaowq1 小时前
AST 安全求值
java·开发语言
我们从未走散1 小时前
AI 生图平台如何避免资损:用“扣款与凭据同事务”构建三态账本
开发语言·数据库·php