Նոր լեզվի անցնելը միշտ մեծ քայլ է, հատկապես, երբ ձեր թիմի անդամներից միայն մեկն ունի այդ լեզվի հետ նախնական փորձ: Այս տարվա սկզբին մենք փոխեցինք Stream-ի հիմնական ծրագրավորման լեզուն Python-ից Go-ի: Այս գրառումը կբացատրի որոշ պատճառներ, թե ինչու մենք որոշեցինք թողնել Python-ը և անցնել Go-ին:

Go-ի օգտագործման պատճառները

Պատճառ 1 — Արդյունավետություն

Գնալը չափազանց արագ է: Կատարումը նման է Java-ի կամ C++-ի: Մեր օգտագործման դեպքում Go-ն սովորաբար 30 անգամ ավելի արագ է, քան Python-ը: Ահա մի փոքր հենանիշ խաղ, որը համեմատում է Go vs Java:

Պատճառ 2 — Լեզվի կատարողականը կարևոր է

Շատ հավելվածների համար ծրագրավորման լեզուն պարզապես սոսինձ է հավելվածի և տվյալների բազայի միջև: Լեզվի կատարումն ինքնին սովորաբար մեծ նշանակություն չունի:

Stream-ը, այնուամենայնիվ, API մատակարար է, որն ապահովում է սնուցման ենթակառուցվածքը 500 ընկերությունների և ավելի քան 200 միլիոն վերջնական օգտագործողների համար: Մենք տարիներ շարունակ օպտիմալացնում ենք Cassandra-ն, PostgreSQL-ը, Redis-ը և այլն, բայց, ի վերջո, դուք հասնում եք ձեր օգտագործած լեզվի սահմաններին:

Python-ը հիանալի լեզու է, բայց դրա կատարումը բավականին դանդաղ է օգտագործման դեպքերի համար, ինչպիսիք են սերիալիզացիան/ապասերիալացումը, դասակարգումը և համախմբումը: Մենք հաճախ բախվում էինք կատարողականի հետ կապված խնդիրների, որտեղ Cassandra-ն 1ms-ով կպահանջի տվյալները առբերելու համար, իսկ Python-ը ծախսում էր հաջորդ 10ms-ը՝ դրանք օբյեկտների վերածելու համար:

Պատճառ 3 – Մշակողի արտադրողականություն և չափազանց կրեատիվ չլինել

Նայեք Go կոդի այս փոքրիկ հատվածին Ինչպես սկսել եմ գնալ ձեռնարկից: (Սա հիանալի ձեռնարկ է և լավ մեկնարկային կետ՝ մի քիչ Go-ից վերցնելու համար):

Եթե ​​դուք նոր եք Go-ում, ապա շատ բան չկա, որը ձեզ կզարմացնի, երբ կարդաք այդ փոքրիկ կոդի հատվածը: Այն ցուցադրում է բազմաթիվ հանձնարարություններ, տվյալների կառուցվածքներ, ցուցիչներ, ձևաչափում և ներկառուցված HTTP գրադարան:

Երբ ես առաջին անգամ սկսեցի ծրագրավորել, ես միշտ սիրում էի օգտագործել Python-ի ավելի առաջադեմ հնարավորությունները: Python-ը թույլ է տալիս բավականին կրեատիվ լինել ձեր գրած կոդով: Օրինակ, դուք կարող եք.

  • Օգտագործեք MetaClasses՝ կոդերի սկզբնավորման ժամանակ դասերը ինքնագրանցելու համար
  • Փոխանակեք «Ճշմարիտը» և «կեղծը»:
  • Ավելացնել գործառույթներ ներկառուցված գործառույթների ցանկում
  • Օպերատորների գերբեռնվածությունը կախարդական մեթոդների միջոցով

Այս հատկանիշները զվարճալի են խաղալը, բայց, ինչպես կհամաձայնեն ծրագրավորողների մեծ մասը, դրանք հաճախ դժվարացնում են կոդը հասկանալը ուրիշի աշխատանքը կարդալիս:

Գոն ձեզ ստիպում է հավատարիմ մնալ հիմունքներին: Սա շատ հեշտ է դարձնում որևէ մեկի կոդը կարդալը և անմիջապես հասկանալ, թե ինչ է կատարվում:

Նշում. որքանով է դա հեշտ իսկապես կախված է ձեր օգտագործման դեպքից, իհարկե: Եթե ​​ցանկանում եք ստեղծել հիմնական CRUD API, ես դեռ խորհուրդ կտամ Django + DRF կամ Rails:

Պատճառ 4 — Համաժամանակյաություն և ալիքներ

Որպես լեզու, Go-ն փորձում է ամեն ինչ պարզ պահել: Այն շատ նոր հասկացություններ չի ներկայացնում: Ուշադրության կենտրոնում է մի պարզ լեզու ստեղծելը, որի հետ աշխատելը աներևակայելի արագ և հեշտ է: Միակ տարածքը, որտեղ այն ստանում է նորարարություն, գորուտիններն ու ալիքներն են: (100%-ով ճիշտ լինելու համար CSP հասկացությունը սկսվել է 1977 թվականին, ուստի այս նորամուծությունն ավելի շատ հին գաղափարի նոր մոտեցում է:

Գորութինները շատ էժան են ստեղծելու համար և պահանջում են միայն մի քանի ԿԲ լրացուցիչ հիշողություն: Քանի որ Goroutine-ները շատ թեթև են, հնարավոր է, որ դրանցից հարյուրավոր կամ նույնիսկ հազարավոր գործարկվեն միաժամանակ:

Դուք կարող եք շփվել գորուտինների միջև՝ օգտագործելով ալիքները: Go-ի գործարկման ժամանակը լուծում է ամբողջ բարդությունը: Գորութինների և ալիքների վրա հիմնված համաժամանակյա մոտեցումը շատ հեշտ է դարձնում բոլոր հասանելի պրոցեսորային միջուկները և միաժամանակյա IO-ի գործարկումը՝ այդ ամենը առանց զարգացումը բարդացնելու: Համեմատելով Python/Java-ի հետ՝ goroutine-ի վրա գործառույթ գործարկելը պահանջում է նվազագույն կաթսայատան կոդ: Դուք պարզապես կատարում եք ֆունկցիայի կանչը «գնալ» հիմնաբառով.

https://tour.golang.org/concurrency/1

Միաժամանակության նկատմամբ Go-ի մոտեցումը շատ հեշտ է աշխատել: Դա հետաքրքիր մոտեցում է Node-ի համեմատ, որտեղ մշակողը պետք է ուշադիր ուշադրություն դարձնի, թե ինչպես է մշակվում ասինխրոն ծածկագիրը:

Գոյում զուգահեռության մեկ այլ մեծ կողմը ռասայի դետեկտորն է։ Սա հեշտացնում է պարզել, թե արդյոք ձեր ասինխրոն կոդում առկա են մրցավազքի պայմաններ:

Ահա մի քանի լավ ռեսուրսներ՝ Go-ի և ալիքների հետ սկսելու համար.

Պատճառ 5 — Արագ կազմման ժամանակ

Go-ում գրված մեր ամենամեծ միկրո ծառայությունը ներկայումս կազմում է 6 վայրկյան: Go-ի արագ կոմպիլյացիայի ժամանակները արտադրողականության մեծ հաղթանակ են՝ համեմատած Java-ի և C++-ի նման լեզուների հետ, որոնք հայտնի են կոմպիլյացիայի դանդաղ արագությամբ: Ես սիրում եմ թրով կռվել, բայց ավելի լավ է անել ամեն ինչ, քանի դեռ ես հիշում եմ, թե ինչ պետք է անի կոդը.

Պատճառ 6 - Թիմ ստեղծելու ունակություն

Նախ, եկեք սկսենք ակնհայտից. Go-ի մշակողներն այնքան էլ շատ չեն՝ համեմատած ավելի հին լեզուների հետ, ինչպիսիք են C++-ը և Java-ն: Ըստ StackOverflow-ի՝ մշակողների 38%-ը գիտի Java-ն, 19.3%-ը գիտի C++ և միայն 4.6%-ը գիտի Go-ն: GitHub տվյալները ցույց են տալիս նման միտում. Go-ն ավելի լայնորեն օգտագործվում է, քան այնպիսի լեզուները, ինչպիսիք են Erlang-ը, Scala-ն և Elixir-ը, բայց ավելի քիչ տարածված, քան Java-ն և C++-ը:

Բարեբախտաբար, Go-ն շատ պարզ և հեշտ սովորվող լեզու է: Այն ապահովում է ձեզ անհրաժեշտ հիմնական հատկանիշները և ուրիշ ոչինչ: Նրա ներդրած նոր հասկացություններն են «հետաձգել» հայտարարությունը և go routines-ի և ալիքների հետ միաժամանակության ներկառուցված կառավարումը: (Մաքուրիստների համար. Go-ն առաջին լեզուն չէ, որն իրականացնում է այս հասկացությունները, պարզապես առաջինն է, որը դրանք հանրաճանաչ է դարձնում:) Ցանկացած Python, Elixir, C++, Scala կամ Java մշակող, որը միանում է թիմին, կարող է արդյունավետ լինել Go-ում մեկ ամսվա ընթացքում, քանի որ իր պարզությամբ։

Մենք հասկացանք, որ ավելի հեշտ է ստեղծել Go մշակողների թիմ՝ համեմատած շատ այլ լեզուների: Եթե ​​դուք մարդկանց աշխատանքի եք ընդունում մրցակցային էկոհամակարգերում, ինչպիսիք են Բոլդերը և Ամստերդամը, սա կարևոր առավելություն է:

Պատճառ 7 — Ուժեղ էկոհամակարգ

Մեր մեծության թիմի համար (~20 հոգի) էկոհամակարգը կարևոր է: Դուք պարզապես չեք կարող արժեք ստեղծել ձեր հաճախորդների համար, եթե ստիպված լինեք նորից հորինել ֆունկցիոնալության յուրաքանչյուր փոքրիկ հատվածը: Go-ն մեծ աջակցություն ունի մեր օգտագործած գործիքներին: Պինդ գրադարաններն արդեն հասանելի էին Redis-ի, RabbitMQ-ի, PostgreSQL-ի, Template parsing-ի, Task scheduling-ի, Expression վերլուծության և RocksDB-ի համար:

Go-ի էկոհամակարգը մեծ հաղթանակ է համեմատած այլ նոր լեզուների հետ, ինչպիսիք են Rust-ը կամ Elixir-ը: Այն, իհարկե, այնքան էլ լավ չէ, որքան Java-ն, Python-ը կամ Node-ը, բայց այն ամուր է և շատ հիմնական կարիքների համար դուք կգտնեք բարձրորակ փաթեթներ արդեն հասանելի:

Պատճառ 8 - Gofmt, Կոդերի կիրառման ձևաչափում

Սկսենք նրանից, թե ինչ է Gofmt-ը: Եվ ոչ, դա հայհոյանք չէ: Gofmt-ը հրամանի տողի հիանալի ծրագիր է, որը ներկառուցված է Go կոմպիլյատորում՝ ձեր կոդը ձևաչափելու համար: Ֆունկցիոնալության առումով այն շատ նման է Python-ի autopep8-ին: Թեև Սիլիկոնյան հովիտը այլ կերպ է պատկերված, մեզանից շատերը չեն սիրում վիճել ներդիրների և բացատների մասին: Կարևոր է, որ ձևաչափումը հետևողական լինի, բայց իրական ձևաչափման ստանդարտը այնքան էլ կարևոր չէ: Gofmt-ը խուսափում է այս ամբողջ քննարկումից՝ ունենալով ձեր կոդը ձևաչափելու մեկ պաշտոնական եղանակ:

Պատճառ 9 - gRPC և արձանագրության բուֆերներ

Go-ն ունի առաջին կարգի աջակցություն արձանագրությունների բուֆերների և gRPC-ի համար: Այս երկու գործիքները շատ լավ են աշխատում միասին միկրոծառայությունների կառուցման համար, որոնք պետք է հաղորդակցվեն RPC-ի միջոցով: Դուք միայն պետք է գրեք մանիֆեստ, որտեղ դուք սահմանում եք RPC զանգերը, որոնք կարող են կատարվել և ինչ փաստարկներ են դրանք վերցնում: Ե՛վ սերվերը, և՛ հաճախորդի կոդը ավտոմատ կերպով ստեղծվում են այս մանիֆեստից: Ստացված այս կոդը և՛ արագ է, և՛ ունի շատ փոքր ցանցային տարածություն և հեշտ է օգտագործել:

Նույն մանիֆեստից դուք կարող եք հաճախորդի կոդը ստեղծել նույնիսկ շատ տարբեր լեզուների համար, ինչպիսիք են C++, Java, Python և Ruby: Այսպիսով, ներքին տրաֆիկի համար այլևս ոչ միանշանակ REST վերջնակետեր, որոնց համար ամեն անգամ պետք է գրեք գրեթե նույն հաճախորդի և սերվերի կոդը: .

Golang-ի օգտագործման թերությունները

Թերություն 1 — Շրջանակների բացակայություն

Go-ն չունի մեկ գերիշխող շրջանակ, ինչպիսին է Rails-ը Ruby-ի համար, Django-ն Python-ի համար կամ Laravel-ը PHP-ի համար: Սա բուռն բանավեճի թեմա է Go համայնքում, քանի որ շատ մարդիկ պաշտպանում են, որ սկզբում չպետք է օգտագործեք շրջանակ: Ես լիովին համաձայն եմ, որ դա ճիշտ է որոշ օգտագործման դեպքերի համար: Այնուամենայնիվ, եթե ինչ-որ մեկը ցանկանում է ստեղծել պարզ CRUD API, նրանք շատ ավելի հեշտ ժամանակ կունենան Django/DJRF-ի, Rails Laravel-ի կամ Phoenix-ի հետ:

Թերություն 2 — Սխալների կառավարում

Go-ն կառավարում է սխալները՝ պարզապես ֆունկցիայից սխալ վերադարձնելով և ակնկալելով, որ ձեր զանգի կոդը կկարգավորի սխալը (կամ այն ​​կվերադարձնի զանգի կույտը): Թեև այս մոտեցումն աշխատում է, հեշտ է կորցնել այն սխալի շրջանակը՝ համոզվելու համար, որ դուք կարող եք նշանակալից սխալ տրամադրել ձեր օգտատերերին: Սխալների փաթեթը լուծում է այս խնդիրը՝ թույլ տալով ձեր սխալներին համատեքստ և շարվածք ավելացնել:

Մեկ այլ խնդիր այն է, որ հեշտ է մոռանալ պատահականորեն կարգավորել սխալը: Ստատիկ վերլուծության գործիքները, ինչպիսիք են errcheck-ը և megacheck-ը, հարմար են այս սխալներից խուսափելու համար:

Թեև այս լուծումները լավ են աշխատում, այն այնքան էլ ճիշտ չի թվում: Դուք ակնկալում եք, որ սխալների պատշաճ մշակումը կաջակցվի լեզվով:

Թերություն 3 — Փաթեթի կառավարում

Go-ի փաթեթի կառավարումը ոչ մի կերպ կատարյալ չէ: Լռելյայնորեն, այն չունի կախվածության որոշակի տարբերակ նշելու միջոց, և վերարտադրվող կառուցումներ ստեղծելու միջոց չկա: Python-ը, Node-ը և Ruby-ն ունեն փաթեթների կառավարման ավելի լավ համակարգեր: Այնուամենայնիվ, ճիշտ գործիքների դեպքում Go-ի փաթեթի կառավարումը բավականին լավ է աշխատում:

Դուք կարող եք օգտագործել Dep՝ ձեր կախվածությունները կառավարելու համար, որպեսզի թույլատրեք նշել և ամրացնել տարբերակները: Բացի դրանից, մենք ներդրել ենք բաց կոդով գործիք, որը կոչվում է VirtualGo, որը հեշտացնում է Go-ում գրված բազմաթիվ նախագծերի վրա աշխատելը:

Python ընդդեմ Go

Հետաքրքիր փորձերից մեկը, որը մենք անցկացրեցինք, մեր ռեկարգված հոսքի գործառույթն ընդունելն էր Python-ում և այն վերաշարադրել Go-ում: Նայեք դասակարգման մեթոդի այս օրինակին.

Ինչպես Python-ը, այնպես էլ Go ծածկագիրը պետք է կատարեն հետևյալը` այս դասակարգման մեթոդին աջակցելու համար.

  1. Վերլուծիր միավորի արտահայտությունը: Այս դեպքում մենք ցանկանում ենք այս «simple_gauss(time)*popularity» տողը վերածել ֆունկցիայի, որն ընդունում է ակտիվությունը որպես մուտքագրում և վերադարձնում միավորը որպես արդյունք:
  2. Ստեղծեք մասնակի գործառույթներ JSON կոնֆիգուրացիայի հիման վրա: Օրինակ, մենք ուզում ենք, որ «պարզ_գաուսը» անվանի «decay_gauss»՝ 5 օր սանդղակով, 1 օր օֆսեթով և 0.3 քայքայման գործակիցով:
  3. Վերլուծեք «կանխադրված» կոնֆիգուրացիան, որպեսզի ունենաք հետադարձ կապ, եթե որոշակի դաշտ սահմանված չէ գործունեության վրա:
  4. Օգտագործեք 1-ին քայլի ֆունկցիան՝ ֆիդում բոլոր գործողությունները գնահատելու համար:

Վարկանիշային կոդի Python տարբերակի մշակումը տևել է մոտավորապես 3 օր: Դա ներառում է կոդը գրելը, միավորի թեստերը և փաստաթղթերը: Հաջորդը, մենք ծախսել ենք մոտավորապես 2 շաբաթ՝ օպտիմալացնելով կոդը: Օպտիմալացումներից մեկը միավորների արտահայտությունը (simple_gauss(time)*popularity) թարգմանել էր վերացական շարահյուսական ծառի: Մենք նաև ներդրեցինք քեշավորման տրամաբանությունը, որը նախապես հաշվարկեց հաշիվը ապագայում որոշակի ժամանակների համար:

Ի հակադրություն, այս կոդի Go տարբերակի մշակումը տևեց մոտավորապես 4 օր: Կատարումը լրացուցիչ օպտիմալացում չի պահանջում: Այսպիսով, մինչ զարգացման սկզբնական մասնիկը Python-ում ավելի արագ էր, Go-ի վրա հիմնված տարբերակը, ի վերջո, պահանջում էր էականորեն ավելի քիչ աշխատանք մեր թիմից: Որպես հավելյալ առավելություն՝ Go կոդը գործել է մոտավորապես 40 անգամ ավելի արագ, քան մեր բարձր օպտիմիզացված Python կոդը:

Այժմ սա ընդամենը մեկ օրինակ է այն արդյունավետության, որը մենք զգացել ենք՝ անցնելով Go-ին: Դա, իհարկե, համեմատում է խնձորը նարինջի հետ.

  • Վարկանիշային կոդը իմ առաջին նախագիծն էր Go-ում
  • Go կոդը ստեղծվել է Python կոդից հետո, ուստի օգտագործման դեպքն ավելի լավ է հասկացվել
  • Արտահայտությունների վերլուծության Go գրադարանը բացառիկ որակի էր

Ձեր վազքը տարբեր կլինի: Մեր համակարգի որոշ այլ բաղադրիչները զգալիորեն ավելի շատ ժամանակ պահանջեցին Go-ում կառուցելու համար՝ համեմատած Python-ի հետ: Որպես ընդհանուր միտում, մենք տեսնում ենք, որ Go կոդի մշակումը մի փոքր ավելի մեծ ջանքեր է պահանջում: Այնուամենայնիվ, մենք շատ ավելի քիչ ժամանակ ենք ծախսում օպտիմալացնելու կոդը կատարման համար:

Էլիքսիր ընդդեմ Գնալու — Երկրորդ տեղը զբաղեցնողը

Մեկ այլ լեզու, որը մենք գնահատեցինք, Էլիքսիրն է։ Էլիքսիրը կառուցված է Erlang վիրտուալ մեքենայի վրա: Դա հետաքրքրաշարժ լեզու է, և մենք դա համարում էինք, քանի որ մեր թիմի անդամներից մեկը մեծ փորձ ունի Erlang-ի հետ:

Մեր օգտագործման դեպքերի համար մենք նկատեցինք, որ Go-ի հումքի կատարումը շատ ավելի լավն է: Ե՛վ Go-ն, և՛ Elixir-ը հիանալի աշխատանք կկատարեն՝ սպասարկելով հազարավոր միաժամանակյա հարցումներ: Այնուամենայնիվ, եթե նայեք անհատական ​​հարցումների կատարմանը, Go-ն էականորեն ավելի արագ է մեր օգտագործման դեպքում: Մեկ այլ պատճառ, թե ինչու մենք ընտրեցինք Go over Elixir-ը, էկոհամակարգն էր: Մեր պահանջած բաղադրիչների համար Go-ն ուներ ավելի հասուն գրադարաններ, մինչդեռ, շատ դեպքերում, Elixir գրադարանները պատրաստ չէին արտադրական օգտագործման համար: Ավելի դժվար է նաև մշակողներ պատրաստել/գտնել Elixir-ի հետ աշխատելու համար:

Այս պատճառները հավասարակշռությունը թեքեցին Գոյի օգտին: Elixir-ի համար նախատեսված Phoenix շրջանակը, սակայն, հիանալի տեսք ունի և անպայման արժե նայել:

Եզրակացություն

Go-ը շատ կատարողական լեզու է, որը մեծ աջակցություն ունի միաժամանակության համար: Այն գրեթե նույնքան արագ է, որքան այնպիսի լեզուները, ինչպիսիք են C++-ը և Java-ն: Թեև մի փոքր ավելի շատ ժամանակ է պահանջվում Go-ի միջոցով իրեր կառուցելու համար՝ համեմատած Python-ի կամ Ruby-ի հետ, դուք կխնայեք կոդի օպտիմալացման վրա ծախսված տոննա ժամանակ:

Stream-ում մենք ունենք մշակողների փոքր թիմ, որն ապահովում է ավելի քան 200 միլիոն վերջնական օգտագործողների հոսքերը: Go-ի համադրությունը հիանալի էկոհամակարգի, հեշտ մուտքագրման նոր մշակողների համար, արագ կատարման, հաստատ աջակցության միաժամանակության և ծրագրավորման արդյունավետ միջավայր այն դարձնում է հիանալի ընտրություն:

Stream-ը դեռ օգտագործում է Python-ը մեր վահանակի, կայքի և մեքենայական ուսուցման համար անհատականացված հոսքերի համար: Մենք շուտով հրաժեշտ չենք տա Python-ին, բայց առաջ գնալով բոլոր կատարողական ինտենսիվ ծածկագիրը կգրվի Go-ում:

Եթե ​​ցանկանում եք ավելին իմանալ Go-ի մասին, ստուգեք ստորև թվարկված բլոգային գրառումները: Stream-ի մասին ավելին իմանալու համար այս ինտերակտիվ ձեռնարկը հիանալի մեկնարկային կետ է:

Ավելին կարդալ Գոլանգին անցնելու մասին

Սովորում ենք Go

Այս գրառումն ի սկզբանե գրվել է GetStream.io-ի գլխավոր տնօրեն Թիերի Շելենբախի կողմից: Բլոգի բնօրինակ գրառումը կարելի է գտնել https://getstream.io/blog/switched-python-go/ կայքում:

✉️ ԲաժանորդագրվեքCodeburst-իշաբաթական մեկ անգամ Email Blast,🐦 ՀետևեքCodeburst-ին -ում >Twitter, և🕸️ Իմացեք ամբողջական փաթեթի վեբ մշակում: