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

相关推荐
程序媛学姐6 分钟前
SpringKafka错误处理:重试机制与死信队列
java·开发语言·spring·kafka
2401_8401922714 分钟前
如何学习一门计算机技术
开发语言·git·python·devops
巷北夜未央28 分钟前
Python每日一题(14)
开发语言·python·算法
浮尘笔记37 分钟前
go-zero使用elasticsearch踩坑记:时间存储和展示问题
大数据·elasticsearch·golang·go
雾月551 小时前
LeetCode 914 卡牌分组
java·开发语言·算法·leetcode·职场和发展
Y.O.U..1 小时前
今日八股——C++
开发语言·c++·面试
weixin_307779131 小时前
使用C#实现从Hive的CREATE TABLE语句中提取分区字段名和数据类型
开发语言·数据仓库·hive·c#
Xiaok10181 小时前
解决 Hugging Face SentenceTransformer 下载失败的完整指南:ProxyError、SSLError与手动下载方案
开发语言·神经网络·php
绿草在线1 小时前
Mock.js虚拟接口
开发语言·javascript·ecmascript
go_bai2 小时前
Linux环境基础开发工具——(2)vim
linux·开发语言·经验分享·笔记·vim·学习方法