Чтобы рассказать о преимуществах языка GO, мы должны начать с истории языка GO...
Эта статья написанаОфициальный аккаунт Tencent Technology Engineeringопубликовано вОблако Tencent + сообщество
В 2007 году Роб Пайк, главный инженер-программист Google, которому надоел C++, собрал Роберта Гриземера и Кена Томпсона и решил создать новый язык для замены C++, которым стал Golang. Хотя язык GO, появившийся в 21 веке, не может заменить C++, как ожидалось, его производительность исполнения, близкая к C, эффективность разработки языка, близкая к аналитической, и почти идеальная скорость компиляции стали популярны во всем мире. Большинство из них используют Golang для разработки, особенно в облачных проектах.Надо сказать, что Golang глубоко укоренился в сердцах людей. Для нового проекта без исторической нагрузки Golang может быть лучшим выбором.
Роб Пайк, известный как отец языка GO, сказал, что ваше согласие с языком GO зависит от того, согласны ли вы с тем, что меньше значит больше или меньше значит меньше (меньше значит больше или меньше значит меньше). Роб Пайк очень просто резюмировал всю философию дизайна языка GO, ярко и ярко воплощая простоту и практичность.
Многие люди называют язык GO языком C 21-го века, потому что GO не только обладает простотой и производительностью C, но также предоставляет различные практические функции разработки на стороне сервера в интернет-среде 21-го века, позволяя разработчикам разрабатывать в уровень языка.Вы можете легко получить то, что вы хотите.
История развития
В сентябре 2007 года Роб Пайк скомпилировал C++ на Google Distributed Compilation Platform. Во время долгого ожидания он и Роберт Гриземер обсудили некоторые ключевые вопросы языков программирования. Они считали, что упрощение языков программирования Продолжая добавлять новые функции в раздутый язык, большее улучшение. Затем они убедили Кена Томпсона рядом с ними, прежде чем компиляция была закончена, что им нужно что-то с этим делать. Несколько дней спустя они запустили проект под названием Golang в качестве эксперимента в свободное время.
В мае 2008 года Google обнаружил огромный потенциал языка GO и получил полную поддержку от Google, и эти люди начали уделять все свое время дизайну и разработке языка GO.
Ноябрь 2009 Выпущена первая версия языка GO. Март 2012 Выпущена первая официальная версия Go1.0.
В августе 2015 года вышла go1.5, эта версия считается исторической. Полностью удалить часть языка C, использовать GO для компиляции GO, а небольшое количество кода реализовано на ассемблере. Кроме того, они пригласили Рика Хадсона, авторитетного эксперта в области управления памятью, для перепроектирования GC, поддержки параллельного GC и решения проблемы задержки GC (STW), которая подвергалась широкой критике. И в последующих версиях GC был дополнительно оптимизирован. В go1.8 задержку GC в том же бизнес-сценарии можно контролировать в пределах 1 мс с нескольких секунд в go1.1. Для решения проблемы GC можно сказать, что язык GO почти устранил все слабые места в разработке на стороне сервера.
В процессе итерации версии языка GO функции языка в основном не сильно изменились и в основном сохранили эталон GO1.1 и официальное обещание, что новая версия полностью совместима с кодом, разработанным в рамках старой версии. На самом деле, команда разработчиков GO очень осторожно добавляет новые языковые функции и проводит постоянную оптимизацию с точки зрения стабильности, скорости компиляции, эффективности выполнения и производительности сборщика мусора.
Команда разработчиков
Лагерь разработчиков языка GO можно назвать беспрецедентно мощным, среди его основных членов есть много исторических личностей в индустрии компьютерного программного обеспечения, которые оказали глубокое влияние на развитие компьютерного программного обеспечения. Кен Томпсон из Bell Labs разработал язык B, создал операционную систему Unix (первоначально реализованную на языке B), а затем разработал язык C с Деннисом Ритчи в процессе разработки Unix, а затем провел рефакторинг с использованием языка C. Операционная система Юникс. Деннис Ритчи и Кен Томпсон известны как отцы Unix и языка C, и в 1983 году они были совместно награждены премией Тьюринга за выдающийся вклад в разработку компьютерного программного обеспечения. Роб Пайк, также из Bell Labs, важный член команды Unix, изобрел язык Limbo и разработал кодировку UTF-8 совместно с Кеном Томпсоном, одним из авторов «Среды программирования Unix» и «Практики программирования».
Можно сказать, что за языком GO стоит большое дерево Google, и в городе сидит много хороших людей, это настоящее «быдло второго поколения».
Знаменитый Docker полностью реализован в GO, самая популярная в отрасли система управления оркестрацией контейнеров kubernetes полностью реализована в GO, а последующий Docker Swarm полностью реализован в GO. Кроме того, существуют различные известные проекты, такие как etcd/consul/flannel и т. д., которые реализованы с помощью GO. Некоторые люди говорят, что причина, по которой язык GO известен, заключается в том, что он догнал облачную эру, но почему мы не можем сказать иначе: это также язык GO, который способствует развитию облака?
Помимо облачных проектов, есть такие компании, как Toutiao и UBER, которые также полностью реструктурировали свой бизнес с использованием языка GO.
Ключевые особенности языка GO
Причина, по которой язык GO такой мощный, заключается в том, что при разработке сервера он всегда может понять болевые точки программистов и решить проблемы самым прямым, простым, эффективным и стабильным способом. Здесь мы не будем подробно обсуждать конкретный синтаксис языка GO, а только познакомим вас с ключевыми аспектами языка, которые имеют большое значение для упрощения программирования, следуйте по стопам мастеров и познакомьтесь с философией дизайна GO. ИДТИ.
Ключевые особенности языка GO в основном включают следующие аспекты:
- Параллелизм и сопрограммы
- общение на основе сообщений
- Богатые и полезные встроенные типы данных
- Функция с несколькими возвращаемыми значениями
- механизм отсрочки
- отражение
- Высокопроизводительный HTTP-сервер
- Управление проектированием
- спецификация программирования
В сегодняшнюю эпоху многоядерных процессоров важность параллельного программирования очевидна. Конечно, многие языки поддерживают многопоточное, многопроцессорное программирование, но, к сожалению, это не так просто и приятно реализовать и контролировать. Разница с Golang заключается в том, что уровень языка поддерживает параллелизм сопрограмм (горутин) (сопрограммы, также известные как микропотоки, легче, чем потоки, имеют меньшие накладные расходы и более высокую производительность) и очень просты в эксплуатации. предоставляет ключевые слова (go) Используется для запуска сопрограмм, и на одном компьютере могут быть запущены тысячи сопрограмм.
По сравнению с многопоточностью в JAVA и реализацией сопрограмм в GO, это явно более прямолинейно и просто. В этом прелесть GO. Он решает проблемы простым и эффективным способом. Ключевое слово go, пожалуй, самый важный символ языка GO.
общение на основе сообщений
В процессе асинхронного параллельного программирования недостаточно удобно и быстро запустить сопрограмму. Обмен сообщениями между сопрограммами также является очень важной частью, иначе каждая сопрограмма станет дикой лошадью и не поддается контролю. В языке GO для межсопрограммного взаимодействия используется метод связи, основанный на передаче сообщений (вместо используемого большинством языков метода связи, основанного на разделяемой памяти), а в качестве базового типа данных используется канал сообщений (channel), с помощью ключа типа Word (chan) определяется потокобезопасность для параллельных операций. Это также революционно в реализации языка. Видно, что сами языки GO не настолько просты, чтобы в них не было итогового результата, именно они предоставят пользователям наиболее практичную и наиболее выгодную возможность решения задач в самой простой и прямой форме.
Канал используется не только для простого обмена сообщениями, но также может выполнять множество очень практичных и удобных функций. Например, реализация пула TCP-соединений, ограничение тока и т. д., которые непросто реализовать в других языках, но язык GO легко это делает.
Как скомпилированный язык, язык GO также поддерживает очень обширные типы данных в дополнение к традиционным целым числам, числам с плавающей запятой, символам, массивам, структурам и другим типам. С точки зрения практичности, он также изначально поддерживает типы строк, типы срезов (массивы переменной длины), типы словарей, сложные типы, типы ошибок, типы каналов и даже произвольные типы (Interface{}), и очень полезно использовать , удобный. Такие как строки и типы срезов, простота работы почти аналогична Python.
Кроме того, в качестве базового типа данных используется тип error (ошибка), а использование try...catch больше не поддерживается на уровне языка.Это следует расценивать как очень смелое и революционное нововведение, и оно неудивительно, что многие люди жалуются, что язык GO невзрачный. Однако, выходя за рамки традиционной концепции, разработчики ГО считают, что в процессе программирования для обеспечения надежности и стабильности программы очень важна точная обработка исключений, и только после завершения каждой логической обработки четко информировать Вызов верхнего уровня, если есть исключение, и вызов верхнего уровня обрабатывает исключение четко и своевременно, так что надежность и стабильность программы могут быть гарантированы в высокой степени. Хотя это приведет к большому количеству суждений об ошибках в процессе программирования, это, несомненно, повысит бдительность разработчика при обработке исключений. Практика показала, что трудно писать ненадежный код, если он написан строго в стиле, рекомендованном GO. Конечно, предпосылкой является то, что вы не отвергаете его, а признаете.
В поддержке функций с несколькими возвращаемыми значениями нет ничего нового в языках, и Python — одна из них. Разрешение функциям возвращать несколько значений может эффективно упростить программирование в некоторых сценариях. Стиль программирования, рекомендуемый языком GO, заключается в том, что последний параметр, возвращаемый функцией, является типом ошибки (при условии, что в теле логики может возникнуть исключение), поэтому необходимо поддерживать несколько возвращаемых значений на уровне языка. .
Механизм обработки задержки задержки
В языке GO предусмотрено ключевое слово defer, которое можно использовать для указания тела логики, которое необходимо отложить, то есть до возврата тела функции или при возникновении паники. Этот механизм очень удобен для обработки логики post-mortem, например, для предотвращения возможных утечек ресурсов как можно раньше.
Можно сказать, что defer — еще одна очень важная и практичная функция языка после goroutine и channel.Введение defer может в значительной степени упростить программирование, и это более естественно в описании языка, что значительно повышает читабельность кода.
Будучи компилируемым языком со строгой типизацией, Golang, естественно, не так гибок, как язык синтаксического анализа. Как и PHP, например, он слабо типизирован и может напрямую выполнять новые операции над содержимым строковой переменной, что, очевидно, невозможно в компилируемых языках. Однако Golang предоставляет любой тип (interface{}) и мощные возможности отражения типов (reflect). В совокупности гибкость разработки близка к гибкости аналитического языка. С точки зрения динамического вызова логики, реализовать его по-прежнему очень просто. В этом случае, каковы преимущества языка синтаксического анализа, такого как PHP, по сравнению с GO? Лично я пишу PHP почти 10 лет, внедрил фреймворки для разработки, библиотеки базовых классов и различные публичные компоненты.Хотя производительность выполнения недостаточна, эффективности разработки более чем достаточно, и когда я сталкиваюсь с Golang, эти преимущества кажутся быть менее очевидным.
Как серверный язык, появившийся в эпоху Интернета, способность обслуживать пользователей имеет важное значение. GO имеет собственный высокопроизводительный сервер HTTP/TCP/UDP на языковом уровне.Основываясь на параллелизме сопрограмм, GO обеспечивает наиболее прямую и эффективную поддержку возможностей для развития бизнеса. Для реализации высокопроизводительного HTTP-сервера на языке GO требуется всего несколько строк кода, что очень просто.
В языке GO есть набор стандартных спецификаций инженерного менеджмента, и пока разработка проекта ведется в соответствии с этой спецификацией, последующие вещи (такие как управление пакетами, компиляция и т.д.) станут очень простыми.
В проекте GO есть два ключевых каталога: один — это каталог src, который используется для хранения всех исходных файлов .go, а другой — каталог bin, который используется для хранения скомпилированных двоичных файлов. В каталоге src, кроме каталога, в котором находится основной основной пакет, все остальные имена каталогов соответствуют соответствующим именам пакетов в прямом каталоге, иначе компиляция завершится ошибкой. Таким образом, компилятор GO может начать с каталога, в котором расположен основной пакет, полностью использовать структуру каталогов и имя пакета для определения структуры проекта и порядка сборки и избежать введения дополнительного файла Makefile, такого как C++.
В процессе компиляции GO единственное, что нам нужно сделать, — это присвоить путь к проекту GO переменной среды с именем GOPATH, чтобы компилятор знал, где находится компилируемый проект GO. Затем войдите в каталог bin и выполните команду go build {имя каталога, в котором находится основной пакет}, чтобы завершить компиляцию проекта за считанные секунды. Скомпилированный двоичный файл можно отправить в ту же ОС для прямого запуска без каких-либо зависимостей от среды.
Спецификация программирования языка GO принудительно интегрирована в язык, например, четкое указание размещения фигурных скобок, обязательная строка предложения, запрет импорта неиспользуемых пакетов, запрещение определения неиспользуемых переменных и предоставление gofmt. инструменты для принудительного форматирования кода и т.д. Как ни странно, это также вызвало недовольство многих программистов: некоторые люди опубликовали XX отсчетов языка GO, и было много обвинений против норм программирования. Вы знаете, с точки зрения технического менеджмента, любая команда разработчиков будет формулировать конкретные спецификации программирования для определенного языка, особенно в такой компании, как Google. Разработчики GO считали, что вместо того, чтобы писать спецификацию в документе, лучше форсировать интеграцию в язык, что является более прямым и использует преимущества командного сотрудничества и управления проектами.
Практика фреймворка быстрой разработки API
Язык программирования — это инструмент, который говорит нам, что мы можем сделать и как сделать это лучше, и его тоже стоит изучить. В этой части будет представлена среда разработки, реализованная на языке GO, а также несколько общих компонентов. Конечно, фреймворки и общедоступные компоненты, другие языки также могут быть реализованы, и проблема здесь заключается в вопросе стоимости. Кроме того, помимо самого языка GO, мы также надеемся, что вы можете получить некоторые идеи для решения проблем из нескольких представленных компонентов, то есть решить проблему определенным образом, и Неслепое написание кода, в конце концов , только решает проблему в точке. Если вы согласны с этим методом, я считаю, что следующий контент может повлиять на ваш будущий метод разработки проекта и существенно повысить эффективность разработки.
Почему мы выбираем язык GO
Выбор языка GO в основном основывается на двух соображениях.
- Производительность выполнения Сократите время отклика API и решите проблему тайм-аута доступа к пакетным запросам. В бизнес-сценарии Uwork пакетный запрос API часто включает в себя множественные вызовы других сервисов интерфейса.В предыдущем режиме реализации PHP было очень сложно выполнять параллельные вызовы, но последовательная обработка не могла принципиально улучшить производительность обработки. Язык GO отличается.С помощью сопрограммы можно легко реализовать параллельную обработку API, чтобы максимизировать эффективность обработки. Благодаря высокопроизводительному HTTP-серверу Golang пропускная способность системы может быть увеличена с сотен уровней PHP до тысяч миль или даже более 10 000 уровней.
- Эффективность разработки Язык GO прост в использовании, эффективен в описании кода, унифицирован в стандартах кодирования и быстр в использовании. С небольшим объемом кода можно добиться стандартизации фреймворка, а бизнес-логику API можно быстро построить с помощью унифицированной спецификации. Он может быстро создавать различные общие компоненты и общедоступные библиотеки классов, повышать эффективность разработки и осуществлять массовое производство в определенных сценариях.
Когда многие люди изучают новый язык или начинают новый проект, они обычно находят среду с открытым исходным кодом, которая, по их мнению, подходит для начала их пути разработки проекта. В этом нет ничего плохого, но я лично считаю, что нам будет полезнее понять его внутреннюю реализацию. Вы могли заметить, что так называемая структура MVC по существу анализирует путь запроса, а затем направляет на соответствующий контроллер (C) в соответствии с сегментом пути запроса, а затем контроллер далее вызывает логику данных (M), после получения data, визуализировать представление (V) и вернуться к пользователю. Во всем процессе ключевой момент заключается в динамическом вызове логики.
Однако реализация платформы API проще, чем реализация структуры веб-страницы, поскольку она не включает рендеринг представления и требует только возврата результата данных пользователю в виде протокола.
На языке GO очень легко реализовать полноценный фреймворк разработки MVC.При интеграции HTTP-сервера основной код всего фреймворка не будет превышать 300 строк.Из этого можно реально ощутить высокую эффективность описания языка GO (если Если вам интересно, вы можете обратиться к неводу проекта с открытым исходным кодом Uwork).
Некоторые люди также говорят, что в языке GO вообще нет фреймворка, подразумевая, что не нужно вводить сверхмощный фреймворк с открытым исходным кодом, а наоборот, он может усложнить простые вещи.
В реальном процессе разработки проекта одного эффективного языка разработки недостаточно.Для дальнейшего повышения эффективности разработки необходимо постоянно накапливать общедоступные базовые библиотеки, чтобы дополнительно абстрагировать и повторно использовать общую базовую логику.
Кроме того, возможности общих компонентов являются основой для массового производства функций, что качественно повысит эффективность разработки. Компонентная модель разработки поможет нам улучшить способность решения проблем от одной точки к другой. Далее мы сосредоточимся на реализации нескольких общих компонентов, при их наличии производительность программистов может быть действительно высвобождена. И эти мощные общие компоненты несложно реализовать на Golang. В то же время, в сочетании с возможностью параллельной обработки Golang, эффективность выполнения будет качественно улучшена по сравнению с версией PHP. Это идеальное сочетание мощности компонентов и эффективности языка.
Компонент общего списка используется в сценариях запроса данных всех возможных двумерных источников данных (таких как MySQL/MongoDB/ES и т. д.) и решает проблему запроса данных с одной стороны. При разработке проекта Uwork он широко используется для реализации массового производства интерфейса запросов данных и списка запросов страниц. Он использует файл конфигурации JSON в качестве центра для реализации запроса к общему источнику данных и автоматически возвращает результат запроса пользователю в виде API или страницы. Во всем процессе почти нет разработки кода, и единственное, что нужно сделать, это написать файлы конфигурации (не код) с единой спецификацией, которая действительно реализует функциональное массовое производство требований к данным запроса.
Выше приведен процесс построения компонента списка общего назначения. Создание такого мощного компонента общего назначения вызовет ли у людей ощущение недосягаемости? На самом деле это не так, пока весь процесс прояснен и идеи построения интегрированы в Golang, это не сложно. В нашем проекте реализация всего компонента решила ряд проблем с запросами данных с менее чем 700 строками кода Go. Кроме того, благодаря параллельной функции Golang реализовано параллельное выполнение полевых процессоров, что еще больше повышает эффективность выполнения компонентов. Можно сказать, что слияние списков общего назначения и Golang — это идеальное сочетание производительности и эффективности.
Компонент общей формы в основном используется для добавления, удаления и изменения базы данных. Этот компонент также широко используется при разработке проектов Uwork.Как и в общем списке, он основан на файле конфигурации JSON для завершения добавления, удаления и изменения данных таблицы данных. В частности, недавно завершенная платформа управления SDB на уровне компонентов реализует обслуживание данных для всей системы с помощью общих форм и обеспечивает бизнес-производство без кода за счет высокой абстракции.
Выше приведен полный процесс построения общей формы, и для реализации одного этого компонента мы использовали менее 1000 строк кода GO, чтобы решить проблему сохранения всех данных таблицы данных.
Сам язык GO поддерживает параллелизм сопрограмм, которые очень легковесны и могут быстро запускать тысячи рабочих единиц сопрограмм. Если количество задач сопрограммы не контролируется должным образом, конечный результат, скорее всего, будет контрпродуктивным, вызывая ненужную нагрузку на внешние или собственные службы. Пул сопрограмм может в определенной степени контролировать количество исполнительных единиц и обеспечивать безопасность выполнения. Реализовать такой пул сопрограмм в Golang очень просто, нужно лишь немного инкапсулировать канал и горутину, и все готово, весь процесс построения занимает менее 80 строк кода.
В процессе разработки API проверка данных всегда является обязательной частью. Если это простая проверка данных, может быть выполнено несколько строк кода, но при сложной проверке данных очень вероятно, что сотни строк кода могут быть не выполнены, особенно при рекурсивной проверке данных. кошмарный сон.
Компонент проверки данных может использовать метод настройки шаблона данных для выполнения общей проверки с использованием определенной логики. Разработчику нужно только настроить соответствующий шаблон данных и сделать простой вызов, чтобы завершить весь процесс проверки. Для такого универсального компонента проверки данных вся конструкция выполняется на языке GO с менее чем 700 строками кода.
резюме
В реальном процессе разработки проекта самым большим улучшением эффективности разработки, несомненно, являются возможности общедоступных компонентов, которые соответствуют бизнес-сценарию системы.Это также оправдывает предложение Роба Пайка (меньше значит меньше, меньше значит больше), сконфигурирована реальная высокая эффективность разработки, и не нужно писать слишком много кода или даже вообще не писать код, чтобы завершить реализацию логики, и этот метод также оптимален для последующих затрат на обслуживание, поскольку он обеспечивает высокую степень унификации.
Эффективность описания языка GO не вызывает сомнений, реализация всех вышеперечисленных общедоступных компонентов не превышает 1000 строк кода, что решает определенную задачу.
(Часть приведенного выше кода была предоставлена в неводе проекта Uwork с открытым исходным кодом)
Оценка эффективности
Описание среды стресс-теста:
- Служба работающей машины: один неработающий B6, 24-ядерный процессор, 64 ГБ памяти.
- Среда PHP API: Nginx+PHP-FPM, CI framework. Среди них Nginx запускает 10 подпроцессов, каждый подпроцесс получает максимум 1024 соединения, а php-fpm использует статический режим для запуска 2000 резидентных подпроцессов.
- Среда Golang API: скомпилируйте с помощью go1.8.6 и напрямую загрузите процесс Golang API Server (HttpServer), независимо от настройки.
- Заказчик инициирует тестовую программу запросов: написана на Golang, одновременно сопрограммируется, работает на другом независимом бездействующем B6, 24-ядерный процессор, 64G памяти, в последовательности 1-2000 различных уровней (размер шага параллелизма 50), параллелизм выполнено 20 000 запросов.
Сравнение результатов стресс-тестов
В структуре Golang API, когда количество параллелизма > 50, число запросов в секунду при обработке колеблется около 6,5 Вт/с. Производительность стабильна, во время стресс-теста ошибок не зарегистрировано.
Nginx+php-fpm выводит только exit('ok') в index.php, когда число параллелизма > 50, скорость обработки QPS колеблется около 1 Вт/с. Производительность стабильна, во время стресс-теста ошибок не зарегистрировано.
Во фреймворке Nginx+php-fpm+CI логика выполняется до конкретной точки бизнес-логики и выводится выход («ok») При числе параллелизма > 50 скорость обработки QPS колеблется в районе 750/с. И производительность нестабильна, и количество ошибок увеличивается по мере увеличения количества параллелизма во время стресс-теста.
В ходе стресс-теста можно обнаружить, что нет никакого сравнения между Golang и PHP с точки зрения производительности выполнения; в то время как структура HTTP API, реализованная Golang, производительность QPS на одной машине достигает 6,5 Вт / с без нагрузки, что является все еще очень удовлетворительно.
На что обратить внимание при разработке
Ниже приведены некоторые проблемы, возникающие в реальном процессе разработки, только для справки:
Обработка исключений единообразно использует ошибку, не используйте panic/recover для имитации throw...catch, я сделал это сначала, но позже обнаружил, что это совершенно самодовольно.
Нативная ошибка слишком проста, а в реальном процессе разработки API разные исключения должны сопровождаться разными кодами возврата, исходя из этого необходимо заново инкапсулировать ошибку.
Любой исполнитель логики сопрограммы должен иметь обработку восстановления исключения defer recovery() в самом начале логики, иначе паника, возникающая в горутине, приведет к падению всего процесса, и необходимо избежать некоторых логических ошибок, вызывающих глобальные последствия .
В Golang операции над переменными (кроме типов chan) не являются потокобезопасными, включая базовые типы, такие как int, поэтому вы должны учитывать блокировку при одновременной работе с глобальными переменными, особенно при параллельных операциях с картами.
Все приобретения значений ключа карты должны судить о существовании.Лучше всего единообразно инкапсулировать подобные операции, чтобы избежать ненужных исключений во время выполнения.
При определении типа данных среза постарайтесь предварительно установить длину, чтобы избежать ненужной внутренней реорганизации данных.
Эта статья была разрешена автором для публикации сообщества Tencent Cloud +, исходная ссылка: https://cloud.tencent.com/developer/article/1145176?fromSource=waitui.
Добро пожаловать в сообщество Tencent Cloud+ или подпишитесь на общедоступную учетную запись WeChat облачного сообщества (QcloudCommunity), чтобы как можно скорее получить больше массовой технической практики по сухим товарам~