А где стоит ГО?

В языке программирования есть типы - логические, строковые, целые числа или более сложные структуры, известные как классы или структуры. Языки программирования могут быть классифицированы как типизированные, структурно типизированные или номинально типизированные, в зависимости от того, как типы оцениваются и присваиваются различным конструкциям (таким как переменные, выражения, функции, параметры функций и т. Д.) Языка программирования.

По сути, категоризация определяет, как объекты оцениваются и выводятся как определенные типы.

Языки с утиным типом используют Утиный тест, чтобы оценить, можно ли оценить объект как определенный тип. Утиный тест гласит:

Если он похож на утку, плавает, как утка, и крякает, как утка, то, вероятно, это утка.

* Я буду использовать синтаксис GO для объяснения идей - читайте эти примеры как псевдокод - он не имеет ничего общего с правилами языка GO.

Следующий фрагмент кода является примером языка Duck-Typed. Кряква - это Утка, потому что у нее есть функция кряк.

type Mallard struct {
}
func (m Mallard) quack() {
}
func makeDuckQuack(duck Duck) {
    duck.quack()
}
func main() {
     makeDuckQuack(Mallard{})
}

В приведенном выше примере не имеет значения, какой тип Duck - это может быть интерфейс или другой тип - но для функции makeDuckQuack единственное требование - передать объект в качестве параметра, который поддерживает функцию quack.

Для языков с утиным типом обычно нет проверок во время компиляции. Оценка и интерпретация типа происходят во время выполнения - и это может привести к ошибкам во время выполнения.

Например, следующий фрагмент кода будет компилироваться нормально, но создаст ошибку времени выполнения, поскольку Dog не выполняет quack ().

type Dog struct {
}
func (d Dog) bark() {
}
func makeDuckQuack(duck Duck) {
    duck.quack()
}
func main() {
     makeDuckQuack(Dog{})
}

Python и Javascript - популярные языки Duck Typed.

Языки с номинальной типизацией, находящиеся на другом конце спектра, ожидают, что прикладные программисты будут явно вызывать тип для интерпретации компилятором.

type Duck interface {
     quack()
}
type Mallard struct { //Mallard doesn't implement Duck interface
}
func (m Mallard) quack() {
}
func makeDuckQuack(duck Duck) {
    duck.quack()
}
func main() {
     makeDuckQuack(Mallard{}) //This will not work as Mallard doesn't explicitly implement Duck.
}

В приведенном выше примере программист приложения должен специально реализовать интерфейс Duck. Можно утверждать, что явная взаимосвязь означает большую удобочитаемость.

Явное определение отношения между Mallard и Duck также означает, что пакет, содержащий структуру Mallard, зависит от пакета, содержащего Duck структура. Это может быть не всегда хорошо - и увеличивает сложность всего приложения.

Яркими примерами языков с именной типизацией являются Java, C ++.

Языки со структурной типизацией находятся где-то посередине, где программисту приложений не нужно явно определять тип для интерпретации, но компилятор языка выполняет проверки во время компиляции, чтобы гарантировать целостность программы.

type Duck interface {
     quack()
}
type Mallard struct { //Mallard doesn't implement Duck interface
}
func (m Mallard) quack() {
}
type Dog struct {
}
func (d Dog) bark() {
}
func makeDuckQuack(duck Duck) {
    duck.quack()
}
func main() {
     makeDuckQuack(Mallard{}) // Okay     
     makeDuckQuack(Dog{}) // Not Okay
}

В приведенном выше примере программисту не нужно указывать, что Mallard является Duck. Компилятор языка интерпретирует Mallard как Duck - потому что у него есть функция quack. И Dog не Duck -, потому что Dog не крякает.

GO - это язык со структурным типом.

Заключение

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

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

Языки со структурной типизацией обеспечивают баланс - для них требуются проверки во время компиляции и не требуется явного объявления зависимостей.

До программирования с помощью GO (структурная типизация) я в основном программировал на Java (номинальная типизация). Мне нравится гибкость, обеспечиваемая языками структурной типизации - без ущерба для безопасности типов во время компиляции.