0Pricing
Go Academy · 课时

构造器模式

编写符合 Go 惯用方式的构造器

构造器模式 是 CoddyKit 上的免费 Go Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。

为什么需要构造函数

Go 没有用于类型的 new 关键字,也没有类构造函数。惯例是使用名为 New... 的函数验证输入,并返回已初始化的值或指针。

简单的 New 函数

返回一个指针,以确保调用方使用共享实例:

package main
import "fmt"

type Server struct {
    Host string
    Port int
}

func NewServer(host string, port int) *Server {
    return &Server{Host: host, Port: port}
}

func main() {
    s := NewServer("localhost", 8080)
    fmt.Println(s.Host, s.Port)
}

在构造函数中进行验证

构造函数适合验证输入并返回错误:

package main
import ("errors"; "fmt")

type Config struct{ Workers int }

func NewConfig(workers int) (*Config, error) {
    if workers < 1 {
        return nil, errors.New("workers must be >= 1")
    }
    return &Config{Workers: workers}, nil
}

func main() {
    c, err := NewConfig(4)
    fmt.Println(c, err)
}

函数式选项模式

函数式选项模式允许使用可选配置,而不会破坏 API:

package main
import "fmt"

type Server struct{ host string; port int; timeout int }
type Option func(*Server)

func WithPort(p int) Option    { return func(s *Server) { s.port = p } }
func WithTimeout(t int) Option { return func(s *Server) { s.timeout = t } }

func NewServer(host string, opts ...Option) *Server {
    s := &Server{host: host, port: 8080, timeout: 30}
    for _, o := range opts { o(s) }
    return s
}

func main() {
    s := NewServer("localhost", WithPort(9090), WithTimeout(60))
    fmt.Println(s.port, s.timeout)
}

构建器模式

对于复杂对象,构建器模式会将设置方法串联起来并返回结果:

package main
import "fmt"

type QueryBuilder struct{ table, where string; limit int }

func (q *QueryBuilder) Table(t string) *QueryBuilder { q.table = t; return q }
func (q *QueryBuilder) Where(w string) *QueryBuilder { q.where = w; return q }
func (q *QueryBuilder) Limit(n int)   *QueryBuilder { q.limit = n; return q }
func (q *QueryBuilder) Build() string {
    return fmt.Sprintf("SELECT * FROM %s WHERE %s LIMIT %d", q.table, q.where, q.limit)
}

func main() {
    sql := (&QueryBuilder{}).Table("users").Where("age>18").Limit(10).Build()
    fmt.Println(sql)
}

返回值还是指针

当结构体较小且不可变时返回值;当结构体较大、可变或实现接口时返回指针:

  • 小型配置结构体 → 值
  • 有状态对象(服务器、客户端、池)→ 指针
  • 如果使用指针接收者实现接口 → 指针

默认值模式

使用默认值函数或结构体字面量设置合理的默认值,然后再应用选项:

package main
import "fmt"

type Cache struct{ maxSize int; ttlSecs int }

func defaultCache() Cache { return Cache{maxSize: 100, ttlSecs: 300} }

func NewCache(opts ...func(*Cache)) *Cache {
    c := defaultCache()
    for _, o := range opts { o(&c) }
    return &c
}

func main() {
    c := NewCache(func(c *Cache) { c.maxSize = 500 })
    fmt.Println(c.maxSize, c.ttlSecs) // 500 300
}

单例模式

使用 sync.Once 确保共享资源只初始化一次:

package main
import ("fmt"; "sync")

type DB struct{ DSN string }

var (
    instance *DB
    once     sync.Once
)

func GetDB(dsn string) *DB {
    once.Do(func() { instance = &DB{DSN: dsn} })
    return instance
}

func main() {
    db1 := GetDB("postgres://...")
    db2 := GetDB("ignored")
    fmt.Println(db1 == db2) // true
}

测试构造函数

返回错误的构造函数易于测试:

package main
import ("errors"; "fmt")

type Pool struct{ size int }

func NewPool(size int) (*Pool, error) {
    if size <= 0 { return nil, errors.New("size must be positive") }
    return &Pool{size: size}, nil
}

func main() {
    _, err := NewPool(-1)
    fmt.Println(err) // size must be positive
    p, _ := NewPool(5)
    fmt.Println(p.size) // 5
}

避免使用 init()

init() 函数会自动运行,难以测试。相比在 init() 中进行隐式初始化,更推荐使用返回错误的显式构造函数。

快速检查

函数式选项模式解决了什么问题?

回顾:构造函数模式

要点:

  • 使用 New... 函数作为构造函数
  • 验证失败时返回错误
  • 使用函数式选项实现灵活的可选配置
  • 使用构建器模式创建复杂的查询或配置对象
  • 相比 init(),优先使用显式构造函数

练习提示

使用函数式选项实现一个 NewHTTPClient 构造函数。支持 WithTimeout、WithBaseURL 和 WithMaxRetries 选项。

常见问题解答

「构造器模式」课时是免费的吗?

是的 — 「构造器模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。

「构造器模式」这节课中我会学到什么?

编写符合 Go 惯用方式的构造器 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Go Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「构造器模式」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Go Academy 课中编写并运行代码吗?

能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 定义和使用结构体
  2. 结构体上的方法
  3. 构造器模式
  4. 匿名结构体与组合
← 返回 Go Academy