Является ли идиоматичным использование упаковщиков нового типа в Go для идентификаторов? - PullRequest
1 голос
/ 15 октября 2019

В других статически типизированных языках, таких как Haskell, Scala или Rust, иногда для таких вещей, как идентификаторы, можно было бы обернуть их в специальные типы, чтобы помочь компилятору отлавливать ошибки (например, предотвращая передачу в другую область действия String). ) и улучшить удобочитаемость кода путем кодирования ответственности на уровне типа.

Некоторые примеры:

newtype UserId = UserId Integer

или

case class UserId(value: Long) extends AnyVal

или

struct UserId(u64);

Все эти предложения (как правило) не требуют затрат времени выполнения и немного добавляют беспорядок для улучшения душевного спокойствия и документации времени разработки на уровне типа.

Go также имеет эту способность:

type UserId uint64

Мой вопрос не в том, возможно ли это, а в том, распространено ли это и / или считается идиоматическим или нет в Go, и почему.

1 Ответ

1 голос
/ 15 октября 2019

Go поддерживает вывод типа на уровне компилятора. В скомпилированном двоичном файле нет времени выполнения.

С этим определением типа

type UserID uint64

Оба следующих результата должны приводить к одному и тому же двоичному файлу:

uid := UserID(1)
var uid UserID = 1

По моему опыту, среда разработки может одинаково хорошо понимать и то, и другое. И они оба читаемы человеком. Мне кажется, я вижу больше первого в производственном коде, чем второго.

Как упомянуто в комментарии @AndySchweig, это обычно используется, когда переменная имеет значение типа Enum.

type UserType uint

const (
  TypeVisitor UserType = 1
  TypeNormal = 2
  TypeAdmin = 3
)

или

type UserType uint

const (
  TypeVisitor UserType = iota
  TypeNormal
  TypeAdmin
)

Экспортированный const сделает код намного более читабельным:


switch userType {
  case mylib.TypeVisitor:
    // do something
  case mylib.TypeNormal:
    // do something
  case mylib.TypeAdmin:
    // do something
}

...