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

相关推荐
屁股割了还要学1 小时前
【C语言进阶】柔性数组
c语言·开发语言·数据结构·c++·学习·算法·柔性数组
☞下凡☜1 小时前
C语言(20250722)
linux·c语言·开发语言
whhhhhhhhhw1 小时前
Go语言-fmt包中Print、Println与Printf的区别
开发语言·后端·golang
坚持吧20211 小时前
【无标题】word 中的中文排序
开发语言·c#
_oP_i2 小时前
c# openxml 打开加密 的word读取内容
开发语言·c#·word
灵典3362 小时前
JavaSE-图书信息管理系统
java·开发语言
淮北枳丶3 小时前
Java常用命令、JVM常用命令
java·开发语言·jvm
liulilittle3 小时前
C++ Proactor 与 Reactor 网络编程模式
开发语言·网络·c++·reactor·proactor
玩代码3 小时前
Unity里的加力
开发语言·unity
小白的代码日记4 小时前
Java经典笔试题
java·开发语言