πŸ” Π›ΡƒΡ‡ΡˆΠΈΠ΅ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ Go: ΠΏΡƒΡ‚ΡŒ ΠΊ чистому ΠΊΠΎΠ΄Ρƒ

Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ познакомимся с рСкомСндациями ΠΏΠΎ написанию чистого ΠΊΠΎΠ΄Π° Π½Π° Go. РазбСрСмся Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ… с особСнностями языка ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌ Π½Π° ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅ основныС синтаксичСскиС конструкции.

Π Π°Π±ΠΎΡ‚Π° с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ

ΠžΡ‚Π»ΠΈΡ‡ΠΈΠ΅ make ΠΈ new

Make ΠΈ new – это встроСнныС ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡ‹ для выдСлСния памяти. Они ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π² Ρ€Π°Π·Π½Ρ‹Ρ… ситуациях ΠΈ ΠΈΠΌΠ΅ΡŽΡ‚ свои особСнности.

  • new ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Π½ΡƒΠ»Π΅Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ для Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° этот Ρ‚ΠΈΠΏ.
  • make ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ для создания ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ срСзов, ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ ΠΈ ΠΊΠ°Π½Π°Π»ΠΎΠ², Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠΉ экзСмпляр ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°.
  • ОсновноС ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ Π½ΠΈΠΌΠΈ состоит Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ make Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ Ρ‚ΠΈΠΏ, Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ ΠΊ использованию послС создания, Π° new – ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Ρ‚ΠΈΠΏ с Π΅Π³ΠΎ Π½ΡƒΠ»Π΅Π²Ρ‹ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ.
a := new(chan int)   // a ΠΈΠΌΠ΅Π΅Ρ‚ Ρ‚ΠΈΠΏ *chan int
b := make(chan int)  // b ΠΈΠΌΠ΅Π΅Ρ‚ Ρ‚ΠΈΠΏ chan int

Π‘ΠΊΡ€Ρ‹Ρ‚Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ Π² слайсах

Блайс β€” это массив ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π΄Π»ΠΈΠ½Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ элСмСнты ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°. Π’Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅ прСдставляСт собой ссылку Π½Π° Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ массив.

ΠŸΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ со слайсами часто Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ Π·Π°Π΄Π°Ρ‡Π° ΠΈΡ… Β«ΠΏΠ΅Ρ€Π΅Π½Π°Ρ€Π΅Π·ΠΊΠΈΒ» Π½Π° Π±ΠΎΠ»Π΅Π΅ ΠΌΠ΅Π»ΠΊΠΈΠ΅. Π’ ΠΈΡ‚ΠΎΠ³Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ²ΡˆΠΈΠΉΡΡ слайс Π±ΡƒΠ΄Π΅Ρ‚ ΡΡΡ‹Π»Π°Ρ‚ΡŒΡΡ Π½Π° массив исходного. Об этом Π½Π΅ стоит Π·Π°Π±Ρ‹Π²Π°Ρ‚ΡŒ, ΠΈΠ½Π°Ρ‡Π΅ Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ нСпрСдсказуСмоС ΠΏΠΎΡ‚Ρ€Π΅Π±Π»Π΅Π½ΠΈΠ΅ памяти.

Рассмотрим эту ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒ Π½Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹Ρ… ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…:

// ΠŸΠ»ΠΎΡ…Π°Ρ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ° - нСпрСдсказуСмоС ΠΏΠΎΡ‚Ρ€Π΅Π±Π»Π΅Π½ΠΈΠ΅ памяти
func cutSlice() []byte {
	slice := make([]byte, 256)
	fmt.Println(len(slice), cap(slice), &slice[0]) // 256 256 <0x...>
	return slice[:10]
}

func main() {
	res := cutSlice()
	fmt.Println(len(res), cap(res), &res[0]) // 10 256 <0x...>
}

Для прСдотвращСния возникшСй ошибки слСдуСт ΡƒΠ΄ΠΎΡΡ‚ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ производится ΠΈΠ· Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ слайса:

// Π₯ΠΎΡ€ΠΎΡˆΠ°Ρ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ° - Π΄Π°Π½Π½Ρ‹Π΅ скопированы ΠΈΠ· Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ слайса
func cutSlice() []byte {
	slice := make([]byte, 256)
	fmt.Println(len(slice), cap(slice), &slice[0]) // 256 256 <0x...>
	copyOfSlice := make([]byte, 10)
	copy(copyOfSlice, slice[:10])
	return copyOfSlice
}

func main() {
	res := cutSlice()
	fmt.Println(len(res), cap(res), &res[0]) // 10 256 <0x...>
}
Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Go Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°
Π‘ΠΎΠ»ΡŒΡˆΠ΅ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Go Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°Β»
Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Go для собСса
ΠŸΠΎΠ΄Ρ‚ΡΠ½ΡƒΡ‚ΡŒ свои знания ΠΏΠΎ Go Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Go для собСса»
Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π°Π΄Π°Ρ‡ ΠΏΠΎ Go
Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½Ρ‹Π΅ Π·Π°Π΄Π°Ρ‡ΠΈ ΠΏΠΎ Go для ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π°Π΄Π°Ρ‡ ΠΏΠΎ GoΒ»

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ с мноТСствСнным Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ΠΎΠΌ

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² языкС Go ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ нСсколько Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ. Π­Ρ‚ΠΎ называСтся «мноТСствСнным Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ΠΎΠΌΒ». Данная ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒ языка позволяСт Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π½ΠΎ ΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ значСния, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ ошибки ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ объявлСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ с мноТСствСнным Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ΠΎΠΌ Π² Go:

package main

import "fmt"

func swap(a, b int) (int, int) {
	return b, a
}

func main() {
	x, y := swap(1, 2)
	fmt.Println(x, y) // 2 1

	a, _ := swap(3, 4)
	fmt.Println(a) // 4
}

Π’ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ функция swap ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π΄Π²Π° Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° Ρ‚ΠΈΠΏΠ° int ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π΄Π²Π° значСния Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ Ρ‚ΠΈΠΏΠ°, мСняя мСстами исходныС ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅.

МоТно Ρ‚Π°ΠΊΠΆΠ΅ ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ΄Π½ΠΎ ΠΈΠ»ΠΈ нСсколько Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Ρ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ пустой ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ (_).

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ с мноТСствСнным Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ΠΎΠΌ особСнно ΠΏΠΎΠ»Π΅Π·Π½Ρ‹, ΠΊΠΎΠ³Π΄Π° трСбуСтся Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ нСсколько Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ², Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с ошибками ΠΈΠ»ΠΈ ΠΏΡ€ΠΈ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ Π΄Π°Π½Π½Ρ‹Ρ….

ΠŸΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Π°Ρ Π½ΠΈΠΆΠ΅ функция openFile Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π΄Π²Π° значСния, ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… – ошибка ΠΈΠ»ΠΈ nil Π² случаС Π΅Π΅ отсутствия.

func openFile(name string) (*File, error) {
	file, err := os.Open(name)
	if err != nil {
		return nil, err
	}
	return file, nil
}

Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡΡ‹

Π’ Go интСрфСйсы ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ собой Π½Π°Π±ΠΎΡ€ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ², ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰ΠΈΡ… ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Они ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Π°Π±ΡΡ‚Ρ€Π°Π³ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΎΡ‚ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ Ρ‚ΠΈΠΏΠ°ΠΌΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. Π’ΠΎ Π΅ΡΡ‚ΡŒ интСрфСйсы лишь ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π», Π½ΠΎ сами Π΅Π³ΠΎ Π½Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‚.

Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ интСрфСйсы ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ

πŸ’‘Π—Π°ΠΏΠΎΠΌΠ½ΠΈΡ‚Π΅ Π²Π°ΠΆΠ½ΠΎΠ΅ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ
НС стоит ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ интСрфСйсы Π΄ΠΎ ΠΈΡ… использования. Π‘Π΅Π· Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° слоТно ΠΏΠΎΠ½ΡΡ‚ΡŒ, Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π»ΠΈ ΠΎΠ½ΠΈ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹, Π½Π΅ говоря ΡƒΠΆΠ΅ ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π² Π½ΠΈΡ… ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒΡΡ.
package worker  // worker.go

type Worker interface { Work() bool }

func Foo(w Worker) string { ... }
package worker // worker_test.go

type secondWorker struct{ ... }
func (w secondWorker) Work() bool { ... }
...
if Foo(secondWorker{ ... }) == "value" { ... }

НиТС прСдставлСн ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с интСрфСйсами:

// ΠŸΠ»ΠΎΡ…Π°Ρ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ°
package employer

type Worker interface { Worker() bool }

type defaultWorker struct{ ... }
func (t defaultWorker) Work() bool { ... }

func NewWorker() Worker { return defaultWorker{ ... } }

Π’Π΅Ρ€Π½ΠΎΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния Go β€” Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΉ Ρ‚ΠΈΠΏ ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ΡŒ Worker ΠΈΠΌΠΈΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ employer:

// Π₯ΠΎΡ€ΠΎΡˆΠ°Ρ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ°
package employer

type Worker struct { ... }
func (w Worker) Work() bool { ... }

func NewWorker() Worker {
	return Worker{
		...
	}
}

ΠšΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎΡΡ‚ΡŒ ΠΈ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ·ΠΌ

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½

Π“ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ Π΄Π΅ΡˆΠ΅Π²Ρ‹ Π² запускС ΠΈ эксплуатации, Π½ΠΎ Ρƒ Π½ΠΈΡ… Π΅ΡΡ‚ΡŒ конСчная ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния Π·Π°Π½ΠΈΠΌΠ°Π΅ΠΌΠΎΠΉ памяти – Π²Ρ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΈΡ… бСсконСчноС количСство. Π’ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…, срСда выполнСния Go Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° большС Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ.

πŸ’‘ Π—Π°ΠΏΠΎΠΌΠ½ΠΈΡ‚Π΅ Π²Π°ΠΆΠ½ΠΎΠ΅ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ
ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово go Π² своСй ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ для запуска Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹, Π²Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π·Π½Π°Ρ‚ΡŒ, ΠΊΠ°ΠΊ ΠΈ ΠΊΠΎΠ³Π΄Π° ΠΎΠ½Π° Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ.

Если Π²Ρ‹ Π½Π΅ Π·Π½Π°Π΅Ρ‚Π΅ ΠΎΡ‚Π²Π΅Ρ‚Π° Π½Π° Π΄Π²Π° ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½Ρ‹Ρ… вопроса, это ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ возникновСнию ΡƒΡ‚Π΅Ρ‡Π΅ΠΊ памяти.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΠΌΡΡ ΠΊ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ для ΠΈΠ»Π»ΡŽΡΡ‚Ρ€Π°Ρ†ΠΈΠΈ Π΄Π°Π½Π½ΠΎΠΉ ошибки:

func leakGoroutine() {
	ch := make(chan int)
	go func() {
		received := <- ch
		fmt.Println("ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅:", received)
	}
}

Π—Π΄Π΅ΡΡŒ функция leakGoroutine запускаСт Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρƒ, которая Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ ΠΈΠ· ΠΊΠ°Π½Π°Π»Π° ch . Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Π² Π½Π΅Π³ΠΎ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ отправится, ΠΈ сам ΠΎΠ½ Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ закроСтся. Π“ΠΎΡ€ΡƒΡ‚ΠΈΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π° навсСгда, Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ fmt.Println Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚.

ΠžΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ΡƒΡ‚Π΅Ρ‡Π΅ΠΊ

Π˜Π½ΠΆΠ΅Π½Π΅Ρ€Ρ‹ ΠΈΠ· Uber, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ΅ участиС Π² Ρ€Π°Π·Π²ΠΈΡ‚ΠΈΠΈ Go, создали Π΄Π΅Ρ‚Π΅ΠΊΡ‚ΠΎΡ€ ΡƒΡ‚Π΅Ρ‡Π΅ΠΊ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½ – ΠΏΠ°ΠΊΠ΅Ρ‚ goleak, Π½Π°Ρ†Π΅Π»Π΅Π½Π½Ρ‹ΠΉ Π½Π° ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡŽ с ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½Ρ‹ΠΌΠΈ тСстами. Рассмотрим ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с этим инструмСнтом Π½Π° ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅.

ΠŸΡƒΡΡ‚ΡŒ Π΅ΡΡ‚ΡŒ нСкая функция leakGoroutin с ΡƒΡ‚Π΅Ρ‡ΠΊΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹:

func leakGoroutine() {
	go func() {
		time.Sleep(time.Minute)
	}()

	return nil
}

И тСст этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ:

func TestLeakGoroutine(t *Testing.T) {
	defer goleak.VerifyNone(t)

	if err := leak(); err != nil {
		t.Fatal("Fatal message")
	}
}

ΠŸΡ€ΠΈ запускС тСстов появляСтся сообщСниС ΠΎΠ± ошибкС found enexpected goroutines , Π³Π΄Π΅ указываСтся Π²Π΅Ρ€ΡˆΠΈΠ½Π° стСка с ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ½ΠΎΠΉ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½ΠΎΠΉ, Π΅Π΅ состояниС ΠΈ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€.

Π­Ρ‚ΠΎΡ‚ инструмСнт ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»Π΅Π·Π΅Π½ ΠΏΡ€ΠΈ создании ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ позволяСт ΡΠΎΠΊΡ€Π°Ρ‚ΠΈΡ‚ΡŒ врСмя Π½Π° Π½Π°Ρ…ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΈ устранСниС ΡƒΡ‚Π΅Ρ‡Π΅ΠΊ памяти.

ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок ΠΈ восстановлСниС

Ошибки Π² Go прСдставлСны интСрфСйсом error, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ опрСдСляСт ΠΌΠ΅Ρ‚ΠΎΠ΄ Error() string. Π›ΡŽΠ±ΠΎΠΉ Ρ‚ΠΈΠΏ, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ этот ΠΌΠ΅Ρ‚ΠΎΠ΄, ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован ΠΊΠ°ΠΊ ошибка.

type error interface {
    Error() string
}
  • Π§Ρ‚ΠΎΠ±Ρ‹ большС ΡƒΠ·Π½Π°Ρ‚ΡŒ ΠΎΠ± ΠΎΡˆΠΈΠ±ΠΊΠ°Ρ… Π² Go, рСкомСндуСтся ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΡΡ‚Π°Ρ‚ΡŒΡŽ Β«Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π² Go – это Π»Π΅Π³ΠΊΠΎ?Β». Из Π½Π΅Π΅ Π²Ρ‹ ΡƒΠ·Π½Π°Π΅Ρ‚Π΅ ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ эффСктивно Ρ€Π΅ΡˆΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ½Ρ‹Π΅ ситуации Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°Ρ….

ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ ошибки ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ

Π˜Π³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ошибок ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌΡƒ повСдСнию ΠΈ ΡƒΡΠ»ΠΎΠΆΠ½ΠΈΡ‚ΡŒ ΠΎΡ‚Π»Π°Π΄ΠΊΡƒ ΠΊΠΎΠ΄Π°. Рассмотрим ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ способ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ошибок Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Ρ„Π°ΠΉΠ»ΠΎΠΌ:

// ΠΏΠ»ΠΎΡ…ΠΎ
file, err := os.Open("filename.txt")
if err == nil {
    // ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ с Ρ„Π°ΠΉΠ»ΠΎΠΌ
}
// Ρ…ΠΎΡ€ΠΎΡˆΠΎ
file, err := os.Open("filename.txt")
if err != nil {
	log.Fatal(err) // ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибки
}
defer f.Close() // ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΉ Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ для закрытия Ρ„Π°ΠΉΠ»Π°

Π‘Π΅Π· ΠΏΠ°Π½ΠΈΠΊΠΈ, Π½ΠΎ с восстановлСниСм

ΠšΠ»Π°ΡΡΠΈΡ‡Π΅ΡΠΊΠΈΠΉ способ ΡΠΎΠΎΠ±Ρ‰ΠΈΡ‚ΡŒ ΠΎΠ± ошибкС – Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Ρ‚ΠΈΠΏ error. Но Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ Π² Ρ‚Π΅Ρ… случаях, ΠΊΠΎΠ³Π΄Π° Π΅Ρ‘ нСльзя быстро Π²ΠΎΡΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ? Π’ΠΎΠ³Π΄Π° Π½Π° ΠΏΠΎΠΌΠΎΡ‰ΡŒ ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ встроСнная функция panic (часто Π΅Ρ‘ Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ просто Β«ΠΏΠ°Π½ΠΈΠΊΠ°Β»), которая Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ ΠΈ Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ настраиваСмоС сообщСниС ΠΎΠ± ошибкС.

НиТС прСдставлСн ΠΏΡ€ΠΈΠΌΠ΅Ρ€ простой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ с ΠΏΠ°Π½ΠΈΠΊΠΎΠΉ:

package main

import "fmt"

func examplePanic() {
  panic("Паника - ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π°")
  fmt.Println("Ѐункция examplePanic ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»Π°ΡΡŒ")  
}

func main() {
  examplePanic()
  fmt.Println("Ѐункция main ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»Π°ΡΡŒ")
}

ΠŸΡ€ΠΈ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΠΈ ΠΏΠ°Π½ΠΈΠΊΠΈ функция Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ ΠΈ происходит запуск ΠΎΡΡ‚Π°Π²ΡˆΠΈΡ…ΡΡ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ defer, Π° Ρ‚Π°ΠΊΠΆΠ΅ раскручиваниС стСка Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½. Π’ Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Ρ… условиях Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ слСдуСт ΠΈΠ·Π±Π΅Π³Π°Ρ‚ΡŒ ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Ρ… ситуаций, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ это ставит ΠΏΠΎΠ΄ ΡƒΠ³Ρ€ΠΎΠ·Ρƒ Π±Π΅ΡΠΏΠ΅Ρ€Π΅Π±ΠΎΠΉΠ½ΡƒΡŽ Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, Π°Π²Ρ‚ΠΎΡ€Ρ‹ Go прСдусмотрСли этот нСдостаток ΠΈ создали ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ восстановлСния послС ΠΏΠ°Π½ΠΈΠΊΠΈ – recover. Он позволяСт ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ раскручиваниС стСка ΠΈ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΡƒ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒ Π½Π°Π΄ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΎΠΉ.

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠ΄Π΅ΠΌΠΎΠ½ΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ°, обратимся ΠΊ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ:

package main

import "fmt"

func Recovery() {
	if recoveryResult := recover(); recoveryResult != nil {
		fmt.Println(recoveryResult)
	}
	fmt.Println("ВосстановлСниС...")
}

func Panic() {
	defer Recovery()
	panic("Паника")
	fmt.Println("Ѐункция Panic ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»Π°ΡΡŒ")
}

func main() {
	Panic()
	fmt.Println("Ѐункция main ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»Π°ΡΡŒ")
}

Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ выполнСния ΠΊΠΎΠ΄Π° ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Π²Ρ‹Π²ΠΎΠ΄:

Паника
ВосстановлСниС...
Ѐункция main ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»Π°ΡΡŒ

Π—Π°ΠΌΠ΅Ρ‚ΡŒΡ‚Π΅, Ρ‡Ρ‚ΠΎ функция Panic Π½Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ послС ΠΏΠ°Π½ΠΈΠΊΠΈ. Π­Ρ‚ΠΎ происходит ΠΈΠ·-Π·Π° Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ defer вызываСтся отлоТСнная функция Recovery, которая восстанавливаСт Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. Π”Π°Π»Π΅Π΅ исполнСниС пСрСдаСтся Π² main, Π³Π΄Π΅ происходит ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ΅ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ всСго ΠΊΠΎΠ΄Π°.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Π’Π°ΠΆΠ½ΠΎ ΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ качСство ΠΈ чистота ΠΊΠΎΠ΄Π° зависят Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΡ‚ языка программирования, Π½ΠΎ ΠΈ ΠΎΡ‚ Π½Π°Π²Ρ‹ΠΊΠΎΠ² Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°. ИспользованиС рассмотрСнных ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ² ΠΈ слСдованиС ΠΎΠ±Ρ‰ΠΈΠΌ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ°ΠΌ ΠΏΠΎΠΌΠΎΠ³ΡƒΡ‚ ΡƒΠ»ΡƒΡ‡ΡˆΠΈΡ‚ΡŒ качСство создаваСмого ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ обСспСчСния.

Π₯очСтся Π²Π΅Ρ€ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΡΡ‚Π°Ρ‚ΡŒΡ Π²Π΄ΠΎΡ…Π½ΠΎΠ²ΠΈΡ‚ Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π»Π΅ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ описанныС ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ Π² Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ Π½Π° Go ΠΈ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅Ρ‚Ρ€ΡƒΠ΄Π½ΠΎ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒΡΡ Π΄Π°ΠΆΠ΅ Π½ΠΎΠ²ΠΈΡ‡ΠΊΡƒ. И ΠΏΠΎΠΌΠ½ΠΈΡ‚Π΅, чистый ΠΊΠΎΠ΄ – это ΠΏΡƒΡ‚ΡŒ ΠΊ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌΡƒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρƒ!

ΠœΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹ ΠΏΠΎ Ρ‚Π΅ΠΌΠ΅

Π›Π£Π§Π¨Π˜Π• БВАВЬИ ПО Π’Π•ΠœΠ•

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста
23 ноября 2018

Go vs Python: ΠΈΠ·ΡƒΡ‡Π΅Π½ΠΈΠ΅ основ языка Go Π² сравнСнии с Python

Π­Ρ‚ΠΎ Π½Π΅ сорСвнованиС Π΄Π²ΡƒΡ… языков, Π° просто Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ способ обучСния. Рассмат...
admin
19 сСнтября 2018

TOП-3 языка программирования, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ‹ΡƒΡ‡ΠΈΡ‚ΡŒ Π΄ΠΎ 2019

Π­Ρ‚ΠΎ Π½Π΅ просто Ρ‚Ρ€ΠΈ Π»ΡƒΡ‡ΡˆΠΈΡ… языка программирования, Π° Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ смыслС ΠΏΠΎΠΏΡ‹Ρ‚...
Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста
27 октября 2017

30 Π»ΡƒΡ‡ΡˆΠΈΡ… ΠΊΠ½ΠΈΠ³ для освоСния языка программирования Go

Π˜Ρ‰Π΅Ρ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΏΠΎ Go? ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΠ΅ΠΌ 30 книг для освоСния языка программирования...