0Pricing
Go Academy · Урок

Шаблоны конструкторов

Создание конструкторов в идиоматичном стиле 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 — локальная установка не требуется.

Все уроки этого курса

  1. Определение и использование структур
  2. Методы структур
  3. Шаблоны конструкторов
  4. Анонимные структуры и композиция
← Назад к Go Academy