Шаблоны конструкторов
Создание конструкторов в идиоматичном стиле Go
«Шаблоны конструкторов» — бесплатный урок Go Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения 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)
}Шаблон функциональных параметров
Шаблон функциональных параметров позволяет задавать необязательную конфигурацию, не нарушая программный интерфейс:
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.
Часто задаваемые вопросы
Урок «Шаблоны конструкторов» бесплатный?
Да — полный текст урока «Шаблоны конструкторов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.
Чему я научусь в уроке «Шаблоны конструкторов»?
Создание конструкторов в идиоматичном стиле Go Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Go Academy?
Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Шаблоны конструкторов»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Go Academy?
Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Определение и использование структур
- Методы структур
- Шаблоны конструкторов
- Анонимные структуры и композиция