【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。应该根据实际需求选择性使用。

相关推荐
m0_748708055 小时前
C++中的观察者模式实战
开发语言·c++·算法
qq_537562675 小时前
跨语言调用C++接口
开发语言·c++·算法
wjs20245 小时前
DOM CDATA
开发语言
Tingjct5 小时前
【初阶数据结构-二叉树】
c语言·开发语言·数据结构·算法
猷咪6 小时前
C++基础
开发语言·c++
IT·小灰灰6 小时前
30行PHP,利用硅基流动API,网页客服瞬间上线
开发语言·人工智能·aigc·php
快点好好学习吧6 小时前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
秦老师Q6 小时前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
烟锁池塘柳06 小时前
解决Google Scholar “We‘re sorry... but your computer or network may be sending automated queries.”的问题
开发语言
是誰萆微了承諾6 小时前
php 对接deepseek
android·开发语言·php