Рубрики
Без рубрики

Go v Python. Техническое глубокое погружение

Go v Python Технический Deep Dive Python хорошо известен своим простым, естественным языком Li … Tagged with Go, Python.

Python хорошо известен своим простым, естественным языком, таким как синтаксис, и простота использования. Поскольку официальный язык питона написан в C/C ++, вы можете подумать, что язык, вдохновленный C с акцентом на большую простоту, будет иметь аналогичный синтаксис с Python. Я обнаружил, что GO больше похож на C ++, чем Python. Это не значит, что нет никаких сходств, но они довольно высокие.

Если вы разработчик Python, хотите узнать, что это статья для вас. Моя цель – для тех, кто удобен в Python, сможет, к концу статьи, прочитать, писать и понимать достаточно хорошо, чтобы написать простые программы и понять фрагменты кода, которые они найдут на таких сайтах, как переполнение стека.

Перед техническим глубоким погружением я кратко расскажу о общих случаях использования каждого языка, фундаментальных различиях и правилах синтаксиса GO, которые могут сбить вас с толку, когда вы учитесь Go.

Сценарии использования

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

В общем, если ваша задача по программированию имеет дело с распределенными системами или в значительной степени полагается на параллелизм GO – отличный выбор. Для более общих задач программирования или для анализа данных нет лучшего выбора, чем Python.

Фундаментальные различия

Два больших фундаментальных различия:

  • GO – это составной язык, в то время как Python – это интерпретированный язык.
  • GO – это статически напечатанный язык, в то время как Python – это динамически напечатанный язык.

В случае, если вы не знакомы с различиями между статически, и динамически напечатанные языки здесь – это то, что я имею в виду при использовании настоящих терминов.

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

Не все статически напечатанные языки сильно напечатаны, и не все динамически напечатанные языки слабо напечатаны, однако в случае GO он статически и сильно напечатан, и в случае Python он динамически и слабо набирается.

Синтаксические различия

  • GO статически и сильно напечатан, в то время как Python динамически и слабо набирается.
  • Python позволяет окружать строки отдельные кавычки или двойные цитаты, в то время как GO требует, чтобы строки были окружены двойными цитатами. (т.е. "Это строка в Go" В то время как 'Это ошибка компилятора в Go' )
  • Go использует True/False, пока Python использует True/false.
  • Комментарии в Go Начните с // В то время как на питоне они начинают с # Анкет
  • GO обеспечивает конфиденциальность функций и свойств, в то время как Python поддерживает конфиденциальность только путем соглашения, используя подчеркивание для частного и двойного подчеркивания для действительно частного.
  • GO не заботится о углублении, в то время как Python использует отступление, чтобы определить масштаб.

Техническое глубокое погружение

Ваше путешествие в GO начинается с основных типов данных, доступных на каждом языке. Вы пройдете свой путь через переменные, списки/массивы, DICTS/Карты, функции и классы/структуры, заканчивающиеся параллелизмом и упаковкой.

Типы данных

Go имеет гораздо больше типов данных, чем типы данных Python, а GO намного более конкретны. В таблице ниже показан эквивалентный Python для перемещения типов данных.

буль буль
нить стр
int, uint, int8, uint8, int16, uint16, int32, uint32, int63, int64 инт
float32, float64 плавать
множество список
карта диктат

ПРИМЕЧАНИЕ: Когда вы видите один тип Python, который соответствует нескольким типам GO, это означает, что один тип Python можно использовать для представления любого из перечисленных типов GO.

Вывод – это типы данных в GO (int8, float32 и т. Д.) Намекните на количество битов, используемых для хранения значений. Бинарное представление чисел выходит за рамки этой статьи, но есть отличная рецензия здесь Если тебе любопытно. На данный момент вы можете использовать типы данных int, uint и float64 в Go, не имея многих проблем.

Переменные

Объявление переменных в Python просто и последовательно. Имя переменной идет слева от оператора назначения, = и значение идет справа. GO немного более условно, потому что для этого требуется тип данных на левом знаке = Но в целом синтаксис похож. это.

a = 12
var a int = 12 // Variable `a` is of type int and has value 12

Go также поддерживает тип инференции, которое является механическим Python, использующим для определения типов данных. В типе Go используется, когда ключевое слово var заменяет фактический тип данных или : = Оператор используется вместо = Анкет

var a = 12
a := 12

: = Оператор чувствует себя наиболее питоническим для меня, поэтому я буду использовать это в остальных примерах. Время от времени вы увидите синтаксис с длинным руком, который либо требуется, либо преувеличивать точку.

Назначение одинаково между Python и GO.

a = 1337
a = 1337

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

a = 1337
a = 1337.0
# This is an explicit type conversion in Python
a = float(a)
a := 1337
c := float32(a)

Это сильная система печати GO, которая заставляет конвертированное значение храниться в переменной нового типа.

Как и Python, есть некоторые преобразования, такие как преобразование Int в список, которые не могут быть сделаны автоматически. Правильный способ обработки такого преобразования состоит в том, чтобы построить новый экземпляр объекта, такого как тип (то есть список/массив или DICT/MAP) и использовать преобразованное значение в качестве начального значения, которое является отличным свинцом в списки массивов V.

Массивы V списки

Самое близкое к спискам Python – это массивы. Массивы и списки оба служат одной и той же цели, чтобы держать набор элементов, но они функционируют по -разному. Большие различия есть.

  1. Массивы могут содержать только элементы того же типа, в то время как списки могут содержать элементы любого типа.
  2. Массивы имеют фиксированную длину, в то время как списки будут расти по мере добавления большего количества элементов.

Первые различия, которые вы найдете между массивами и списками, – это то, что они создаются по -разному. Python по -прежнему прямой имеет только один способ создания списка. GO становится немного сложным, потому что у массивов есть емкость и размер.

shopping = ['coffee', 'milk', 'sugar']
var shopping [3]string
var shopping_v1 = []string {"coffee", "milk", "sugar"}
shopping_v2 := []string {"coffee", "milk", "sugar"}
shopping_v3 := [3]string {"coffee", "milk"}

Все массивы в примере GO имеют емкость 3, но разные размеры. Покупки Массив – пустой массив, Shopping_v1 и Shopping_v2 иметь размер 3, и Shopping_v3 имеет размер 2.

В Python вам не придется думать о разнице между пропускной способностью и размером. Список всегда такой большой, как и должно быть, и количество элементов в списке совпадает с длиной списка (т.е. len (Shopping) ). С массивами GO вам нужно будет знать и понять емкость и размер. Емкость – это количество предметов, которые массив может удерживать, в то время как размер – это количество предметов, которые в настоящее время удерживает массив. Эта таблица разрушает емкость и размер каждого массива в предыдущем примере.

0 3 var Shopping [3] строка
3 3 var shopping_v1 = [] string {“кофе”, “молоко”, “сахар”}
3 3 Shopping_v2: = [] string {“кофе”, “молоко”, “сахар”}
2 3 Shopping_v3: = [ 3] string {“кофе”, “молоко”}

Элементы в списке/массиве могут быть извлечены или сохранены в списке/массиве с помощью индекса, как показано в следующих фрагментах кода. Обратите внимание на массивы и списки как начала, так и индекса 0.

shopping = ['coffee', 'milk', 'sugar']
print(shopping[0]) # prints coffee
shopping[0] = 'decaf coffee' # Forgive me :-(
print(shopping) # prints ['decaf coffee', 'milk', 'sugar']
shopping := []string {"coffee", "milk", "sugar"}
fmt.Println(shopping[0]); # prints coffee
shopping[0] = "decaf coffee"
fmt.Println(shopping) // prints ["decaf coffee", "milk", "sugar"]

Наиболее распространенный способ добавить элемент в список в Python – это вызов append () метод GO не позволяет добавлять элементы к массиву, потому что это увеличило бы емкость массива, которая является статичной после объявления массива. При этом, если размер меньше, чем емкость, любое неиспользованное пространство заполняется нулевыми значениями, и эти нулевые значения могут быть перезаписаны так же, как другое другое значение может быть перезаписано с помощью индекса.

shopping = ["coffee", "milk", "sugar"]
shopping.append("filters")
shopping := string[4] {"coffee", "milk", "sugar"}
shopping[3] = "filters" // Arrays start at index 0

Элементы могут быть удалены из списка в Python, используя del ключевое слово Но в Go предмет удаляется путем создания двух ломтиков массива, которые исключают элемент, который будет удален, и сохраняя эти ломтики обратно в исходный массив.

shopping = ['coffee', 'milk', 'sugar']
del shopping[0] # Again forgive me I love coffee too
print(shopping) # prints ['milk', 'sugar']
shopping := [3]string {"coffee", "milk", "sugar"}
shopping = append(shopping[2], shopping[3:])
fmt.Println(shopping) // prints ["milk", "sugar"]

Среции – это общая концепция между Python и GO. Синтаксис очень похож, но они ведут себя совершенно иначе. В Python ломтик – это список, состоящий из элементов из другого списка. Это полная копия, и то, что происходит с ломтиком, не влияет на исходный список.

В ходе ломтик – это окно в массив, поэтому все, что сделано среза, влияет на основной массив, и изменение индексов среза изменяется только то, что элементы видны через окно.

Кроме того, ломтики имеют одинаковый синтаксис.

  • [n] Получает предмет в NTH INDEX
  • [n:] Получает элементы из NTH INDEX через последний пункт и включает в себя последний пункт.
  • [ n: m] Получает элементы из NTH INDEX через MTH INDEX, за исключением элемента в MTH INDEX.
  • [: m ] Получает элементы из 0 -го индекса через N -й индекс, за исключением элемента в NTH Index.

ПРИМЕЧАНИЕ: GO не поддерживает третий параметр в срезах, чтобы указать размер шага между элементами.

Карта V Dict

Если вам нужно больше, чем числовой индекс в набор данных, следующим шагом будет ключ, пара значений. В Python у вас есть словари, чаще называемые DICTS, и на ходу у вас есть карты. Карты имеют одинаковые ограниченные массивы в том смысле, что они ограничены хранением предметов объявленного типа данных. Карты также должны быть построены с использованием Make () функция Make () ручки, выделяющие соответствующее количество памяти, которая снова является детализацией, которую вам не придется рассмотреть в Python.

ace_of_spades = { "suit": "spades", "value": "A"}
ace_of_spades = make(map[string]string)
ace_of_spades["suit"] = "spades"
ace_of_spades["value"] = "A"

Синтаксис для создания карты, вероятно, выглядит странно для разработчиков Python. То, что вы видели из массивов, может помочь упростить это. [3] строка создал массив, способный удерживать 3 строки, каждая из которых может быть доступен по целочисленному индексу. Make (Map [String] String) Создает карту, в которой можно получить доступ к каждому элементу с помощью строкового индекса. Дополнительный бонус карт заключается в том, что они не ограничиваются определенным размером, каким образом массивы были и будут продолжать расти по мере добавления большего количества предметов.

Карты также могут быть построены с использованием : = оператор при посевании карты начальными значениями.

ace_of_spades := map[string]string{"suit": "spades", "value": "A"}

У вас уже есть краткий обзор добавления значения к карте. В Go это то же самое, что добавление значения к дикту в Python.

ace_of_spades = {"suit": "spades", "value": "A"}
ace_of_spades['numeric_value'] = 1
ace_of_spades = map[string]string{"suit": "spades", "value": "A"}
ace_of_spades["numeric_value"] = "14

Удаление элемента для карты также очень похоже на удаление элемента из дикта Python. В Python вы бы использовали дель В то время как в Go вы используете встроенные Удалить функция

ace_of_spades = {'suit': 'spades', 'value': 'A'}
del ace_of_spades['value']
ace_of_spades := map[string]string{"suit": "spades", "value": "A"}
delete(ace_of_spades, "value")

Словаря Pythons имеют .получить () Функция обеспечивает безопасный способ проверить, существует ли ключ. Карты также имеют механизм проверки, существует ли ключ. Похоже, это.

item, exists = ace_of_spades["does not exist"]

В этом примере существует было бы ложным, и пункт была бы пустая строка. Этот же шаблон работает для всех карт. Единственное, что меняется, – это то, какое значение присваивается вещь . Когда ключ существует на карте вещь это значение, связанное с этим ключом, и существует правда. Когда ключа не существует существует ложь, и пункт является нулевым значением для типа данных, хранящегося на карте.

Функции

Функции в Python и go разрешают несколько возвращаемых значений, поддерживают функции высшего порядка и используйте конкретное ключевое слово для объявления функции. Это ключевое слово для Python – дефект и Func в Go. Основное различие между языками заключается в том, что GO требует объявления типа данных для параметров функции и возвращаемых значений, а Python – нет. Подсказка типа Python очень похоже на объявления типа данных GO, поэтому, если вы намекаете, вы будете на шаг вперед.

Вот пример, показывающий необходимые объявления типа данных для Приветствие Функция в Go и той же функции в Python, используя подсказки типа.

# Hints the function takes a string as a parameter and returns a string
def greeting(name: str) -> str:
    return f'Hello {name}!'

print(greeting('Derek')) # Prints Hello Derek!
print(greeting(12)) # Prints Hello 12!
func greeting(name string) string {
  return fmt.Printf("Hello %s!", name)
}

func main() {
  fmt.Println(greeting("Derek")) // Prints Hello Derek!
  fmt.Println(greeting(12)) // Cause a runtime error.
}

Этот пример демонстрирует применяемые данные GO по сравнению с намеком Python. Python не возражает принять целое число, когда тип подсказка для строки, где GO встречается с ошибкой времени выполнения при вызове Приветствие (12) Анкет

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

def greeting(name: str)-> Tuple(str,str):
    return 'Hello', name

result = greeting('World')
print(type(result)) # prints 
func greeting(name string) (string, string) {
   return "Hello", name
}

result_1, result_2 := greeting("World")
fmt.Printf("%T, %T", result_1, result_2) // Prints string, string

Обе сообщества GO и Python используют соглашение о хранении возврата в переменной с именем _ может быть проигнорирован. Похоже, это.

def greeting(name):
  return 'Hello', name

salutation, _ greeting('Derek')
func greeting(name string) (string, string) {
  return "Hello", name
}

salutation, _ = greeting("Derek")

Время охватить расширенные темы Функции высшего порядка , обратный вызов и Закрытие Анкет

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

def english(name: str) -> str:
  return f'Hello {name}!'


def spanish(name: str) -> str:
  return f'Hola {name}!'


def greeting(lang, name: str) -> str:
    return lang(name)


en = english
es = spanish

print(greeting(en, 'Derek')) # Prints Hello Derek!
print(greeting(es, 'Derek')) # Prints Hola Derek!

В этом примере переменные поступка и es закрыты, lang параметр в Приветствие Функция – это обратный вызов, а Приветствие Сама функция является функцией высшего порядка. Go имеет те же возможности, но очень явно относится к типам данных для Параметры и возвращаемые значения не только для выполняемой функции, но и функции, которой она передается. Легче понять объявления типа данных, необходимые путем просмотра кода.

func english(name string) string {
  return fmt.Sprintf("Hello %s!", name)
}

func spanish(name string) string {
  return fmt.Sprintf("Hola %s!", name)
}

func greeting(lang func(string)string, name string) string {
  return lang(name)
}

func main() {
  en := english
  es := spanish

  fmt.Println(greeting(en, "Derek")) // Prints Hello Derek!
  fmt.Println(greeting(es, "Derek")) // Prints Hola Derek!
}

Те же утверждения о коде Python также верны и для этого кода. поступка и es закрыты, lang Параметр в функции приветствия является обратным вызовом, а сама функция приветствия по-прежнему остается функцией высшего порядка. Единственное, что изменилось, – это объявление функции для Приветствие стал монстром. Это заявляет, что функция приветствия ожидает два параметра. Первая – это функция, которая принимает строку и возвращает строку, а второй параметр – это простая строка. Объявление функции для приветствия может быть очищено с помощью указателя функции.

Указатели функций точно так же, как они звучат. Это указатели на функции. Другим способом взглянуть на это является то, что указатели функций – это переменные, которые хранят ссылки на определенную функцию, что именно то, что такое закрытие. Синтаксис для объявления нового указателя функции выглядит так.

type PointerNoParamNoReturn func()
type PointerIntParamNoReturn func(int)
type PointerIntAndStrParamsStrReturn func(int, string)string

Все эти примеры создают указатели функций, но каждый создает новый тип, который может указывать только на функции, которые соответствуют определенной подписи. Последний пример, который является самым сложным, создает новый тип PointerintandStrparamsstrreturn который это указатель функции, который может указывать на любую функцию, первый параметр которого является int, а второй параметр которого – строка и возвращает строку. В основном PointerintandStrparamsstrreturn становится псевдонимом для Func (int, String) String Анкет Вот пример, использующий указатель функции для очистки провозглашения чудовищной функции из предыдущего примера приветствия.

type LangPtr func(string)string

def greeting(lang LangPtr, name string) string {
  return lang(name)
}

func main() {
  // Declares es and en variables of type lang_ptr (i.e. are function pointers)
  var en, es langPtr
  en = english
  es = spanish

  fmt.Println(greeting(en, "Derek")) // Prints Hello Derek!
  fmt.Println(greeting(es, "Derek")) // Prints Hola Derek!
}

Классы вин

Структы-это концепция, которая поступает из C, которая не была разработана, чтобы быть объектно-ориентированным языком, поэтому типичные конструкции OO, такие как классы, были опущены из его грамматики. По -прежнему была необходимость группировать переменные вместе в одном блоке памяти, который C выполнял с помощью структур. C ++ появился после C, добавляя классы, все еще поддерживая структуры. Затем Python появился после того, как C ++ полностью покончил с ними. При использовании CPYTHON реализации структур Python используется без того, чтобы вы ее не знали, но этого достаточно истории.

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

class Card:
  def __init__(self, suit, value):
    self.suit = suit
    self.value = value

ace_of_spades = Card(1, 'S')
type Card struct {
  suit string
  value int
}

func main() {
  ace_of_spades := Card{1, "S"}
}

GO позволяет создавать структуры с использованием позиционных аргументов, как показано в приведенном выше примере, или с аргументами ключевых слов. При создании структуры с позиционными аргументами или объектными литералами, как они называются в GO, первое значение переходит в первое свойство, определенное, второе значение во второе свойство и так далее. Литералы объектов также могут принимать ключевые слова, что заставляет их действовать больше как Python’s ** Кваргс . Похоже, это.

type Card struct {
  suit string
  value int
}

ace_of_spades := Card{value: 1, suit: "S"}

В этом примере порядок значений не имеет значения. Какое -либо значение предусмотрено для костюм Аргумент ключевого слова сохраняется в костюм Свойство struct и любое значение предоставляется для ценность Аргумент ключевого слова сохраняется в значение Свойство структуры.

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

class Card:
  def __init__(self, suit="", value=0):
      self.suit = suit
      self.value = value

suitless_king = Card(value=13)
valueless_heart = Card(suit="H")
type Card struct {
  suit string
  value int
}

suitless_king = Card{value: 13}
valueless_heart = Card{suit: "H"}

После того, как класс/структура становятся созданными свойствами одинаково в Python и Go.

print(ace_of_spades.suit) # Prints S
fmt.Println(ace_of_spades.suit) // Prints S

В Python функция становится методом, когда она вложена в классную объявление, как показано ниже. Go Bolts функционирует с структурой, давая эту функцию доступ к свойствам структуры. Код ниже показывает, как склад Метод может быть добавлен в Рука класс/структура.

class Card:
  def __init__(self, suit, value):
    self.suit = suit
    self.value = value

class Hand:
  def __init__(self, cards: list):
    self.cards = cards

  def fold(self):
      card_1 = f"{self.cards[0].value}:{self.cards[0].suit}"
      card_2 = f"{self.cards[1].value}:{self.cards[1].suit}"
      print(f'Folded with hand: {card_1}, {card_2}')

my_hand = Hand([Card("S", 1), Card("H", 2)])
my_hand.fold() # Prints Folded with hand: 1:S, 2:H
type Card struct {
  suit string
  value int
}

type Hand struct {
  cards [2]Card
}

func (h Hand) fold() {
  card_1 := fmt.Sprintf("%d:%s", h.cards[0].value, h.cards[0].suit)
  card_2 := fmt.Sprintf("%d:%s", h.cards[1].value, h.cards[1].suit)
  fmt.Printf("Folded with hand: %s, %s", card_1, card_2)
}

func main() {
  ace_of_spades := Card{"S", 1}
  two_of_hearts := Card{"H", 2}
  my_hand := Hand{[2]Card{ace_of_spades, two_of_hearts}}
  my_hand.fold() // Prints Folded with hand 1:S, 2:H
}

Декларация склад Функция должна быть странной для разработчиков Python, однако она становится намного более знакомым, когда h Изменен на я Анкет

func (self Hand) Fold() {
  card_1 := fmt.Sprintf("%d:%s", self.cards[0].value, self.cards[0].suit)
  card_2 := fmt.Sprintf("%d:%s", self.cards[1].value, self.cards[1].suit)
  fmt.Printf("Folded with hand: %s, %s", card_1, card_2)
}

Это больше похоже на Python. На этой записке вы знали, что это только соглашение, чтобы назвать первый параметр для метода я ? По правде говоря, этот параметр может быть назван всем, это , я , или что -то совершенно произвольное, как h . Вот код Python с использованием h вместо себя .

class Hand:
  def __init__(h, cards: list):
    h.cards = cards

  def fold(h):
      card_1 = f"{h.cards[0].value}:{h.cards[0].suit}"
      card_2 = f"{h.cards[1].value}:{h.cards[1].suit}"
      print(f'Folded with hand: {card_1}, {card_2}')

Зная, что структуры были взяты из C, этот Python написан частично в C, и как функции прикрепляются к структурам, вы должны иметь достойное представление о том, как выглядит базовый код C/C ++ при работе с себя .

Параллелизм

Потоки, многопроцессорная и асинхронная ввода/вывод поддерживались в Python с 3.4. У каждого есть свой собственный модуль, который может быть импортирован и использовать для запуска кода асинхронно или в своем собственном потоке или процессе. В ходе нет таких модулей. На самом деле это совсем наоборот. Есть синхронизация Пакет, который помогает сделать код синхронным, потому что GO по своей сути является многопоточной и асинхронной. Каждая программа GO выполняется из Goroutine, которая представляет собой легкий поток, управляемый во время выполнения.

Вот где GO, наконец, менее словеса, чем Python. Чтобы запустить новую ветку, все, что вам нужно сделать, это позвонить идти Перед вызовом функции.

import threading
def sum(a, b):
    print(a + b)

t = threading.Thread(target=sum, args=(11, 1,))
t.start() # Kicks off a thread that prints 12
func sum(a int, b int) {
  fmt.Println(a + b)
}

go sum(11, 1) // Prints 12

Получение результатов из потока или передача значений между потоками всегда было сложно. Go решает проблему с каналами, сокращенными для Чан Анкет Используя каналы, легко пропустить значения между goroutines. В Python вы должны использовать ThreadPoolexecutor, который не плохой, но все еще более многословный.

import concurrent.futures

def sum(a, b):
  return a + b

with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
  future = executor.submit(sum, 11, 1)
  print(future.result())
func sum(a int, b int, c (chan int)) {
  c <- a + b // Sends the results of a+b to the channel c
}

func main() {
  int_channel := make(chan int) // Creates a channel for passing integers
  go sum(11, 1, int_channel)
  res := <-int_channel // Gets the value from int_channel and stores it in res
  fmt.Println(res) // Prints 12
}

Когда вы передаете канал другому Goroutine, вы буквально предоставляете канал связи между этими двумя Goroutines. Каналы имеют только один оператор, <- , который утверждает, откуда текутся данные, от. Намекните данные в потоках в Направление стрелы. Итак, в сумма Функциональные данные поступают в канал и в Главный Функциональные данные вытекают из канала в res переменная. С риском редакции, я думаю, что это легче думать о концептуально и выглядит чище.

Параллелизм обрабатывается так по -разному между двумя языками, которые я собираюсь перестать сравнивать сторону с помощью образцов побочного кода на этом этапе. Вы должны иметь достаточно хорошее понимание Goroutines и каналов для прототипа реализации шаблона издателя/потребителя.

Упаковка

Python и Go оба используйте структуру каталога проекта для путей импорта. Концепции будут чувствовать себя знакомыми. Модуль – это файл, заканчивающий в .идти или .py . Пакет – это каталог в вашей файловой системе, а любой модуль под пакетом считается модулем этого пакета. Большие различия

  1. Python допускает детальный импорт пакетов, модулей, классов, функций или переменных, в то время как GO поддерживает только импорт полный пакет, включая модули, классы, функции и переменные, экспортируемые этим пакетом.
  2. Private – это реальная концепция в Go, в отличие от Python, который использует _ и __ Конвенция, чтобы указать, что что -то является частным, но все еще дает доступ к этой вещи.
  3. GO требует, чтобы имя пакета было указано в верхней части каждого модуля.
  4. Имя пакета в объявлении пакета не должно соответствовать имени каталога.

Давайте посмотрим на пример.

sampleapp/
  |_ main.py
  |_ main.go
  |_ messages /
    |_ important.py
    |_ important.go

Учитывая эту структуру каталога, как Python, так и GO будут использовать SAMPLEAPP Как основное имя пакета. Импорт Важно.py и Важно.go выглядеть очень по -другому, хотя. Вот что main.py и main.go может выглядеть как.

from sampleapp.messages import important

important.important()
import "sampleapp/messages"

func main() {
  messages.Important()
}

Это говорит вам, что есть функция с именем Важно в Важно.py и функция с именем Важно где -то в SampleApp/Сообщения Go Package. С тех пор Важно.go единственный модуль под SampleApp/Сообщения ты знаешь Важно Функция объявлена в этом модуле. Вы также можете подумать, что объявление пакета в важности. Go – это Сообщения пакета Потому что функция вызывается с Сообщения. Важно Анкет Помните, что объявленное имя пакета не должно соответствовать имени пакета импорта.

В этом примере скрыта небольшая тонкость. Функция Python – Важно и функция GO Важно С столицей I. Я был очень намерен, чтобы до сих пор был намерен поддерживать корпус, поэтому этот пример будет выделяться. Я сделал это, потому что поступил только на конвенцию, только экспортирует классы функций и переменные, чьи имена начинаются с заглавной буквы. Все, что начинается с письма о нижнем регистре, является частным. Это похоже на конвенцию Pythons, которая _ частное и __ действительно личный, но с Go вы не можете получить доступ к частным свойствам или методам.

Распределение вашей посылки

Real Python уже имеет отличный учебник по Публикация пакета в PYPI Анкет Если вы хотите узнать больше о упаковке, проверьте это.

Основными веществами являются исходные код, должны храниться в каком -то хранилище кода, и должен быть включен файл метаданных, описывающий имя, версию, зависимости и т. Д. Файл метаданных в Python – это setup.py и go.mod в Go. Как только исходный код будет доступен через публичный репозиторий, вы опубликовали свой пакет Go, и нечего делать. С помощью Python вам нужно построить колесный файл из исходного кода, создать учетную запись PYPI и использовать инструмент под названием Twine для публикации колеса для PYPI.

Загрузка и использование пакетов

Опубликованные пакеты легко получить на любом языке. С Python, это PIP установка в то время как в ходе его Go Get Анкет

После загрузки пакета он может быть импортирован аналогично локальным пакетам и модулям. Например, если вы загрузили пакет с именем Хайку Это генерирует случайного хайкуса. Чтобы импортировать пакет в Python, это было бы Импорт Хайку Анкет В Go, это Зависит от того, откуда вы получили пакет. Если бы этот пакет был загружен с моего GitHub, команда Go Get будет Получите github.com/ezzy1337/haiku и импорт будет Импорт "github.com/ezzy1337/haiku" Анкет Однако, если он хранился на TestOffersons GitHub команда Go Get была бы чем -то вроде Получите github.com/ttestofferson/haiku и импорт будет Импорт "github.com/ttestofferson/haiku" Анкет Независимо от того, откуда пришел пакет после импорта, он будет использоваться как любой другой импортированный пакет.

Вывод

Вау, спасибо, что проклялись со мной через все это. Вы должны быть в состоянии поиграть с Go и быть уверенным в том, что вы делаете. У Google есть самостоятельно управляемый Тур Go Что я очень рекомендую, особенно если вы просто хотите поиграть с тем, что вы узнали в этой статье. Имейте в виду синтаксические различия с начала этой статьи, которую я сказал, что, вероятно, вас сбит.

Я хотел бы услышать от вас! Ударьте меня @D3R3Kdrumm0nd в Твиттере с комментариями, вопросами или, если вы просто хотите оставаться в курсе моего следующего проекта.

Оригинал: “https://dev.to/ezzy1337/go-v-python-a-technical-deep-dive-5fni”