2019-10-28 22:26:47 +03:00
-- -
name : Go
category : language
language : Go
2019-11-14 16:17:56 +03:00
filename : learngo - ua . go
2019-10-28 22:26:47 +03:00
contributors :
- [ "Sonia Keys" , "https://github.com/soniakeys" ]
- [ "Christopher Bess" , "https://github.com/cbess" ]
- [ "Jesse Johnson" , "https://github.com/holocronweaver" ]
- [ "Quint Guvernator" , "https://github.com/qguv" ]
- [ "Jose Donizetti" , "https://github.com/josedonizetti" ]
- [ "Alexej Friesen" , "https://github.com/heyalexej" ]
- [ "Clayton Walker" , "https://github.com/cwalk" ]
- [ "Leonid Shevtsov" , "https://github.com/leonid-shevtsov" ]
translators :
- [ "AstiaSun" , "https://github.com/AstiaSun" ]
lang : uk - ua
-- -
Go був створений для того , щоб виконати задачу . Це не останній тренд в теорії мов програмування , а спосіб вирішення реальних проблем .
Він увібрав принципи з імперативних мов зі статичною типізацією .
Go швидко компілюється та виконується , а його багатопоточність легка для
2019-11-01 12:39:36 +03:00
вивчення , оскільки багатоядерні CPU стали буденністю . Ця мова програмування успішно використовується у кодах великих продуктів ( ~ 100 мільйонів в Google , Inc . )
2019-10-28 22:26:47 +03:00
Go має чудову стандартну бібліотеку та чимале ком ' юніті .
` ` ` go
// Однорядковий коментар
/ * Багато -
рядковий коментар * /
2019-11-01 12:39:36 +03:00
// Кожен файл вихідного коду має починатись із ключового слова package.
2019-10-28 22:26:47 +03:00
// main - це спеціальна назва, що оголошує виконуваний код, а не бібліотеку.
package main
2019-11-01 12:39:36 +03:00
// import оголошує бібліотеки, що використовуються в даному файлі.
2019-10-28 22:26:47 +03:00
import (
"fmt" // Пакет стандартної бібліотеки Go.
"io/ioutil" // Цей пакет реалізує деякі I/O функції утиліт.
m "math" // Бібліотека математичних операцій з локальним псевдонімом m.
"net/http" // Так, веб сервер!
"os" // Функції операційної системи, такі як робота з файловою системою.
"strconv" // Перетворення текстових змінних.
)
// Оголошення функції.
// Функція main - особлива. Це вхідна точка для виконуваних програм.
// Ви можете любити це, а б о ж ненавидіти, але Go використовує фігурні дужки.
func main ( ) {
// Println виводить рядок в stdout.
// Ця функція входить у пакет fmt.
fmt . Println ( "Hello world!" )
// Викликати іншу функцію з цього файлу.
beyondHello ( )
}
2019-11-01 12:39:36 +03:00
// Аргументи функцій описуються у круглих дужках.
// Навіть якщо ніякі аргументи не передаються, пусті круглі дужки - обов`язкові.
2019-10-28 22:26:47 +03:00
func beyondHello ( ) {
var x int // Оголошення змінної. Перед використанням змінні обов'язково мають бути оголошені.
x = 3 // Присвоєння значення.
// "Короткі" оголошення використовують := щоб окреслити тип, оголосити та присвоїти значення.
y := 4
sum , prod := learnMultiple ( x , y ) // Функція повертає два значення.
fmt . Println ( "sum:" , sum , "prod:" , prod ) // Просто вивід.
learnTypes ( ) // < y хвилин, потрібно вивчити більше!
}
/ * <- багаторядковий коментар
Функції можуть мати параметри та повертати довільну кількість значень .
2019-11-01 12:39:36 +03:00
В цьому прикладі ` x ` , ` y ` - це аргументи , а ` sum ` , ` prod ` - це змінні , що повертаються .
2019-10-28 22:26:47 +03:00
Зверніть увагу , що ` x ` та ` sum ` мають тип ` int ` .
* /
func learnMultiple ( x , y int ) ( sum , prod int ) {
return x + y , x * y // Повернути два значення.
}
// Кілька вбудованих типів та літералів.
func learnTypes ( ) {
// Короткі оголошення зазвичай виконують все, що необхідно.
str := "Вчи Go!" // рядок (string).
s2 := ` "Необроблений" текст
2019-11-01 12:39:36 +03:00
може містити переноси рядків . ` // Також має тип рядок.
2019-10-28 22:26:47 +03:00
// Н е ASCII символи. Go використовує UTF-8.
g := 'Σ' // руничний тип, псевдонім для int32, містить позицію юнікод кода.
2019-11-01 12:39:36 +03:00
f := 3.14195 // float64, IEEE-754 64-бітне число з плаваючою крапкою.
c := 3 + 4i // complex128, комплексні числа, що являють собою два float64.
2019-10-28 22:26:47 +03:00
2019-11-01 12:39:36 +03:00
// Синтаксис ініціалізації з var.
2019-10-28 22:26:47 +03:00
var u uint = 7 // Беззнаковий цілочисельний тип, проте розмір залежить від імплементації, так само як і int.
var pi float32 = 22. / 7
2019-11-01 12:39:36 +03:00
// Синтаксис перетворення типів з коротким оголошенням.
2019-10-28 22:26:47 +03:00
n := byte ( '\n' ) // Байт - це переіменований uint8.
// Розмір масива фіксований протягом часу виконання.
var a4 [ 4 ] int // Масив з 4 чисел, всі проініціалізовані 0.
a5 := [ ... ] int { 3 , 1 , 5 , 10 , 100 } // Масив проініціалізованих чисел з фіксованим розміром у
// п'ять елементів, що мають значення 3, 1, 5, 10, та 100.
// Зрізи мають динамічний розмір. Переваги є і у масивів, й у зрізів, проте
2019-11-01 12:39:36 +03:00
// останні використовуються частіше.
2019-10-28 22:26:47 +03:00
s3 := [ ] int { 4 , 5 , 9 } // Порівняйте з a5. Тут немає трьокрапки.
s4 := make ( [ ] int , 4 ) // Виділяє пам'ять для зрізу з 4 чисел, проініціалізованих 0.
var d2 [ ] [ ] float64 // Декларація, нічого не виділяється.
bs := [ ] byte ( "a slice" ) // Синтаксис переведення у інший тип.
// Оскільки зрізи динамічні, до них можна додавати елементи за необхідністю.
// Для цієї операції використовується вбудована функція append().
// Перший аргумент - це зріз, до якого додається елемент. Зазвичай
2019-11-01 12:39:36 +03:00
// змінна масиву оновлюється на місці, як у прикладі нижче.
2019-10-28 22:26:47 +03:00
s := [ ] int { 1 , 2 , 3 } // В результаті отримуємо зріз із 3 чисел.
s = append ( s , 4 , 5 , 6 ) // додаємо 3 елементи. Зріз тепер довжини 6.
fmt . Println ( s ) // Оновлений зріз тепер має значення [1 2 3 4 5 6]
// Щоб о б 'єднати два зрізи, замість того, щоб проходитись по всім елементам,
2019-11-01 12:39:36 +03:00
// можна передати посилання на зріз із трьокрапкою, як у прикладі нижче. Таким чином,
2019-10-28 22:26:47 +03:00
// зріз розпакується і його елементи додадуться до зріза s.
s = append ( s , [ ] int { 7 , 8 , 9 } ... )
fmt . Println ( s ) // Оновлений зріз тепер дорівнює [1 2 3 4 5 6 7 8 9]
p , q := learnMemory ( ) // Оголошує змінні p, q, що є вказівниками на числа.
2019-11-01 12:39:36 +03:00
fmt . Println ( * p , * q ) // * іде попереду вказівника. Таким чином, виводяться числа.
2019-10-28 22:26:47 +03:00
2019-11-01 12:39:36 +03:00
// Асоціативний масив (map) - це динамічно розширюваний тип даних, як хеш
2019-10-28 22:26:47 +03:00
// а б о словник в інших мовах програмування
m := map [ string ] int { "three" : 3 , "four" : 4 }
m [ "one" ] = 1
// В Go змінні, які не використовуються, вважаються помилкою.
2019-11-01 12:39:36 +03:00
// Нижнє підкреслення дозволяє "використати" змінну, але проігнорувати значення.
2019-10-28 22:26:47 +03:00
_ , _ , _ , _ , _ , _ , _ , _ , _ , _ = str , s2 , g , f , u , pi , n , a5 , s4 , bs
// Зазвичай це використовується, щоб проігнорувати значення, що повертає функція.
// Наприклад, в скрипті нашвидкоруч можна проігнорувати помилку, яку повертає
// функція os.Create, вважаючи, що файл буде створений за будь-яких умов.
file , _ := os . Create ( "output.txt" )
fmt . Fprint ( file , "Приклад, як відбувається запис у файл." )
file . Close ( )
// Вивід значень змінних.
fmt . Println ( s , c , a4 , s3 , d2 , m )
learnFlowControl ( ) // Рухаємось далі.
}
2019-11-01 12:39:36 +03:00
// Навідміну від більшості інших мов програмування, функції в Go підтримують
2019-10-28 22:26:47 +03:00
// іменоване значення, що повертається.
// Змінні, значення яких повертається функцією, вказуються із зазначенням типу при
2019-11-01 12:39:36 +03:00
// оголошенні функції. Таким чином, можна з легкістю повернути їхні значення в різних
2019-10-28 22:26:47 +03:00
// точках коду, не перелічуючи їх після ключового слова return.
func learnNamedReturns ( x , y int ) ( z int ) {
z = x * y
return // z не потрібно вказувати, при оголошенні описано змінну для повернення.
}
2019-11-01 12:39:36 +03:00
// Go використовує сміттєзбірник. В ньому використовуються вказівники, проте немає
2019-10-28 22:26:47 +03:00
// операцій з вказівниками. Можлива помилка при використовуванні вказівника nil, але не
// при збільшенні значення вказівника (перехід по адресам пам'яті).
func learnMemory ( ) ( p , q * int ) {
2019-11-01 12:39:36 +03:00
// Іменовані змінні, що повертаються, p та q, мають тип вказівника на чисельне значення.
2019-10-28 22:26:47 +03:00
p = new ( int ) // Вбудована функція виділяє нову пам'ять.
// Виділена адреса пам'яті чисельного типу int ініціалізовується 0, p більше не nil.
s := make ( [ ] int , 20 ) // Виділити пам'ять для 20 чисел у вигляді суцільного блоку в пам'яті.
s [ 3 ] = 7 // Присвоїти значення одному з них.
r := - 2 // Оголосити нову локальну змінну.
return & s [ 3 ] , & r // Оператор & повертає адресу в пам'яті о б 'єкта.
}
func expensiveComputation ( ) float64 {
return m . Exp ( 10 )
}
func learnFlowControl ( ) {
// if твердження вимагає фігурні дужки, але не вимагає округлих.
if true {
fmt . Println ( "Кажу ж" )
}
// Форматування стандартизовано командою командного рядка "go fmt".
if false {
// Pout.
} else {
// Gloat.
}
2019-11-01 12:39:36 +03:00
// Використання перемикача (switch) замість ланцюга if-тверджень.
2019-10-28 22:26:47 +03:00
x := 42.0
switch x {
case 0 :
case 1 :
case 42 :
// Кейси не "провалюються". Натомість, є ключове слово `fallthrough`:
// https://github.com/golang/go/wiki/Switch#fall-through (англ)
case 43 :
// Недоступний.
default :
// Кейс за замовчуванням не обов'язковий.
}
// Як і if, формат оголошення циклу for не вимагає круглих дужок:
// Змінні, оголошені всередині if та for - належать цій області видимості.
for x := 0 ; x < 3 ; x ++ { // ++ - це твердження.
fmt . Println ( "iteration" , x )
}
// Тут x == 42.
2019-11-01 12:39:36 +03:00
// For - це єдиний цикл в Go, проте він має кілька різних форм.
2019-10-28 22:26:47 +03:00
for { // Ініціалізація циклу.
break // Упс, помилково зайшли.
continue // Недоступне твердження.
}
// Можна використовувати діапазони, зрізи, рядки, асоціативні масиви, а б о ж
// канал для ітерації в циклі. Діапазон (range) повертає один (канал) а б о два
// значення (масив, зріз, рядок та асоціативний масив).
for key , value := range map [ string ] int { "one" : 1 , "two" : 2 , "three" : 3 } {
// для кожної пари в асоціативному масиві, надрукувати ключ та значення
fmt . Printf ( "key=%s, value=%d\n" , key , value )
}
// якщо потрібне тільки значення, можна застосувати нижнє підкреслення як ключ
for _ , name := range [ ] string { "Bob" , "Bill" , "Joe" } {
fmt . Printf ( "Hello, %s\n" , name )
}
2019-11-01 12:39:36 +03:00
// так само, як і з циклом for, оператор := в розгалуженні означає оголосити
// локальну змінну в області видимості if та присвоїти значення. Далі
2019-10-28 22:26:47 +03:00
// значення змінної проходить перевірку y > x.
if y := expensiveComputation ( ) ; y > x {
x = y
}
2019-11-01 12:39:36 +03:00
// Літерали функцій - це замикання
2019-10-28 22:26:47 +03:00
xBig := func ( ) bool {
return x > 10000 // Посилання на x, що був оголошений раніше, перед switch.
}
x = 99999
fmt . Println ( "xBig:" , xBig ( ) ) // true
x = 1.3e3 // Тобто, тепер x == 1300
fmt . Println ( "xBig:" , xBig ( ) ) // false тепер.
// Функція може бути оголошена та викликана в одному рядку, поводячи с е б е
2019-11-01 12:39:36 +03:00
// як аргумент функції, але за наступних умов:
// 1) літерал функції негайно викликається за допомогою ()
2019-10-28 22:26:47 +03:00
// 2) тип значення, що повертається, точно відповідає очікуваному типу аргументу
fmt . Println ( "Add + double two numbers: " ,
func ( a , b int ) int {
return ( a + b ) * 2
} ( 10 , 2 ) ) // Викликаємо з аргументами 10 та 2
// => Додати + подвоїти два числа: 24
// Коли вам це знадобиться, ви полюбите це
goto love
love :
learnFunctionFactory ( ) // функція, що повертає функцію - це весело(3)(3)
learnDefer ( ) // Швидкий обхід до важливого ключового слова.
learnInterfaces ( ) // Тут на вас чекає крута штука!
}
func learnFunctionFactory ( ) {
// Два наступних твердження роблять однакові дії, але другий приклад частіше
// застосовується
fmt . Println ( sentenceFactory ( "summer" ) ( "A beautiful" , "day!" ) )
d := sentenceFactory ( "summer" )
fmt . Println ( d ( "A beautiful" , "day!" ) )
fmt . Println ( d ( "A lazy" , "afternoon!" ) )
}
2019-11-01 12:39:36 +03:00
// Декоратори звична річ для багатьох мов програмування. В Go їх можна реалізувати
// за допомогою літералів функцій, що приймають аргументи.
2019-10-28 22:26:47 +03:00
func sentenceFactory ( mystring string ) func ( before , after string ) string {
return func ( before , after string ) string {
return fmt . Sprintf ( "%s %s %s" , before , mystring , after ) // новий рядок
}
}
func learnDefer ( ) ( ok bool ) {
2019-11-01 12:39:36 +03:00
// твердження defer змушує функцію посилатись на список. Список
2019-10-28 22:26:47 +03:00
// збережених викликів виконується ПІСЛЯ того, як оточуюча функція закінчує
// виконання.
defer fmt . Println ( "відкладені твердження виконуються у зворотньому порядку (LIFO)." )
defer fmt . Println ( "\nЦе й рядок надрукується першим, тому що" )
// Відкладення зазвичай використовується для того, щоб закрити файл. Таким чином,
2019-11-01 12:39:36 +03:00
// функція, що закриває файл, залишається близькою до функції, що відкриває файл.
2019-10-28 22:26:47 +03:00
return true
}
// Оголошує Stringer як тип інтерфейсу з одним методом, String.
type Stringer interface {
String ( ) string
}
// Оголошує pair як структуру з двома полями, цілими числами x та y.
type pair struct {
x , y int
}
// Оголошує метод для типу pair. pair тепер реалізує Stringer, оскільки pair оголосив
// всі методи в цьому інтерфейсі.
func ( p pair ) String ( ) string { // p тепер називається "приймачем"
2019-11-01 12:39:36 +03:00
// Sprintf - ще одна функція з пакету fmt.
2019-10-28 22:26:47 +03:00
// Крапка використовується, щоб звернутись до полів о б 'єкту p.
return fmt . Sprintf ( "(%d, %d)" , p . x , p . y )
}
func learnInterfaces ( ) {
2019-11-01 12:39:36 +03:00
// Синтаксис з використанням фігурних дужок називається "літералом структури".
2019-10-28 22:26:47 +03:00
// Він застосовується до ініціалізованої структури. Оператор := оголошує
2019-11-01 12:39:36 +03:00
// та ініціалізує p цією структурою.
2019-10-28 22:26:47 +03:00
p := pair { 3 , 4 }
fmt . Println ( p . String ( ) ) // Викликає метод String о б 'єкта p типу pair.
var i Stringer // Оголошує і інтерфейсного типу Stringer.
i = p // Допустиме, оскільки pair реалізує Stringer
// Викликає метод String о б 'єкта і , що має тип Stringer. Виводить те ж саме, що й
// аналогічний метод вище.
fmt . Println ( i . String ( ) )
// Функції з бібліотеки fmt викликають метод String, щоб запросити у о б 'єкта
// своє представлення, яке можна надрукувати.
fmt . Println ( p ) // Виводить те ж саме, що й раніше.
fmt . Println ( i ) // Виводить те ж саме, що й раніше.
learnVariadicParams ( "great" , "learning" , "here!" )
}
// Кількість аргументів функції може бути змінною.
func learnVariadicParams ( myStrings ... interface { } ) {
// Пройтись по значенням всіх аргументів.
// _ - це ігнорування порядкового номеру аргумента в масиві.
for _ , param := range myStrings {
fmt . Println ( "param:" , param )
}
// Передати значення аргументів як параметр змінної величини.
fmt . Println ( "params:" , fmt . Sprintln ( myStrings ... ) )
learnErrorHandling ( )
}
func learnErrorHandling ( ) {
2019-11-01 12:39:36 +03:00
// Ідіома ", ok"використовується, щоб перевірити виконання команди без помилок.
2019-10-28 22:26:47 +03:00
m := map [ int ] string { 3 : "three" , 4 : "four" }
if x , ok := m [ 1 ] ; ! ok { // ok буде мати значення false, тому що 1 не знаходиться
// в асоціативному масиві.
fmt . Println ( "немає таких" )
} else {
fmt . Print ( x ) // x буде мати значення 1, якщо 1 знаходиться в m.
}
// Значення помилки повідомляє не тільки, що все добре, але й може розповісти
// більше про проблему.
if _ , err := strconv . Atoi ( "non-int" ) ; err != nil { // _ ігнорує значення
// виводить помилку 'strconv.ParseInt: parsing "non-int": invalid syntax'
fmt . Println ( err )
}
// Ми розглянемо інтерфейси дещо пізніше. А поки, розглянемо багатопоточність.
learnConcurrency ( )
}
2019-11-01 12:39:36 +03:00
// Канал с - це потокозохищений о б 'єкт для спілкування між потоками.
2019-10-28 22:26:47 +03:00
func inc ( i int , c chan int ) {
c <- i + 1 // Оператор <- виконує операцію "надіслати",якщо змінна каналу
// знаходиться зліва від нього.
}
2019-11-01 12:39:36 +03:00
// inc виконує збільшення значення на 1. Ми використаємо його, щоб збільшувати
2019-10-28 22:26:47 +03:00
// числа рівночасно.
func learnConcurrency ( ) {
// вже знайома функція make, яка раніше використовувалась для виділення пам'яті,
// тут використовується для створення каналу. Make виділяє пам'ять та ініціалізує
2019-11-01 12:39:36 +03:00
// зрізи, асоційовані масиви та канали. Новостворений канал буде передавати
2019-10-28 22:26:47 +03:00
// цілочисельні значення.
c := make ( chan int )
2019-11-01 12:39:36 +03:00
// Запустити три одночасні ґорутини. Числа будуть збільшуватись рівночасно, імовірно
2019-10-28 22:26:47 +03:00
// паралельно якщо пристрій здатний до цього та правильно сконфігурований.
// В с і три ґорутини надсилають значення в один канал.
go inc ( 0 , c ) // Твердження go запускає нову ґорутину.
go inc ( 10 , c )
go inc ( - 805 , c )
// Читаємо три результати з каналу та друкуємо їх.
// Порядок результатів - невідомий!
fmt . Println ( <- c , <- c , <- c ) // якщо канал знаходиться справа від оператора <-,
// він виконує функцію "приймача".
cs := make ( chan string ) // Ще один канал, який примає рядки.
ccs := make ( chan chan string ) // Канал каналів рядків.
go func ( ) { c <- 84 } ( ) // Запустимо нову ґорутину, щоб надіслати значення в канал с .
go func ( ) { cs <- "wordy" } ( ) // Надсилаємо "wordy" в канал cs.
2019-11-01 12:39:36 +03:00
// Ключове слово select має синтаксис, подібний до switch, проте кожен кейс
2019-10-28 22:26:47 +03:00
// включає в с е б е операцію з каналом. Він обирає довільний кейс з наявних, які готові
// комунікувати (передавати дані).
select {
2019-11-01 12:39:36 +03:00
case i := <- c : // Отримане значення може бути присвоєно змінній,
2019-10-28 22:26:47 +03:00
fmt . Printf ( "it's a %T" , i )
case <- cs : // а б о значення може бути проігнороване.
fmt . Println ( "it's a string" )
case <- ccs : // Пустий канал, не готовий комунікувати.
fmt . Println ( "Н е відбудеться." )
}
// Н а цьому етапі, значення було прочитане а б о з с а б о з cs. Одна з двох
// ґорутин завершилась, але інша все ще заблокована.
2019-11-01 12:39:36 +03:00
learnWebProgramming ( ) // Go вміє й у веб. Так, ти хочеш зробити це.
2019-10-28 22:26:47 +03:00
}
// Лиш одна функція з пакету http запускає веб сервер.
func learnWebProgramming ( ) {
2019-11-01 12:39:36 +03:00
// перший аргумент ListenAndServe - це TCP адреса, який сервер буде слухати.
2019-10-28 22:26:47 +03:00
// Другий аргумент - це інтерфейс, а точніше http.Handler.
go func ( ) {
err := http . ListenAndServe ( ":8080" , pair { } )
fmt . Println ( err ) // не ігноруйте помилки
} ( )
requestServer ( )
}
// pair матиме тип http.Handler, якщо реалізувати один його метод, ServeHTTP.
func ( p pair ) ServeHTTP ( w http . ResponseWriter , r * http . Request ) {
// Відповідати на запити можна методом, що належить http.ResponseWriter.
w . Write ( [ ] byte ( "Ти вивчив Go за Y хвилин!" ) )
}
func requestServer ( ) {
resp , err := http . Get ( "http://localhost:8080" )
fmt . Println ( err )
defer resp . Body . Close ( )
body , err := ioutil . ReadAll ( resp . Body )
fmt . Printf ( "\nWebserver said: `%s`" , string ( body ) )
}
` ` `
# # Подальше вивчення
2019-11-01 12:39:36 +03:00
Основним джерелом всієї інформації про Go залишається [ офіційна веб - сторінка ] ( http : //golang.org/). Там можна знайти уроки, інтерактивно пограти та багато про що почитати.
2019-10-28 22:26:47 +03:00
Окрім туру , у [ документації ] ( https : //golang.org/doc/) міститься інформація як писати чистий та ефективний код на Go, документація пакетів та окремих команд, а також історія релізів.
Надзвичайно рекомендується ознайомитись із визначенням мови . Вона легко читається та на диво коротка ( в порівнянні з іншими сучасними мовами ) .
2019-11-01 12:39:36 +03:00
Можна погратись з кодом вище на [ Go playground ] ( https : //play.golang.org/p/tnWMjr16Mm). Спробуй змінити його та запустити із свого браузера. Поміть, що можна використовувати [https://play.golang.org](https://play.golang.org) як [REPL](https://uk.wikipedia.org/wiki/REPL) до тестів та коду в твоєму браузері, без встановлення Go.
2019-10-28 22:26:47 +03:00
2019-11-01 12:39:36 +03:00
В списку для прочитання новачкам в Go - [ вихідний код стандартної бібліотеки ] ( http : //golang.org/src/pkg/). Код всеосяжно задокоментований, тому є найкращим прикладом з боку зручного для прочитання та швидкості розуміння коду на цій мові програмування. Приведений стиль та ідіоми Go.
Крім того , можна просто натиснути на назву функції в [ документації ] ( http : //golang.org/pkg/), щоб перейти до її реалізації.
2019-10-28 22:26:47 +03:00
Іншим прекрасним посиланням для вивчення Go є [ Go by example ] ( https : //gobyexample.com/).
2019-11-01 12:39:36 +03:00
Go Mobile додає підтримку мобільних платформ ( Android та iOS ) . Можна написати нативний код на Go для мобільних застосунків а б о написати бібліотеку , що міститиме прив ' язки ( bindings ) з пакету Go , які можуть бути викликані з Java ( Android ) та Objective - C ( iOS ) . Деталі можна дізнатись на [ веб - сторінці Go Mobile ] ( https : //github.com/golang/go/wiki/Mobile).