72
#golang Специально для devclub.eu @antonarhipov

Something about Golang

Embed Size (px)

Citation preview

#golang

Специально для devclub.eu

@antonarhipov

Pascal C/Asm Perl Java

Краткая история эволюции программиста

Paint

МенюЗакуска

Краткий обзор синтаксиса Go

Основные блюда

Возможности платформыИнструментарий

Десерт

Очень субъективное мнение прожжёного “джависта”

МенюЗакуска

Краткий обзор синтаксиса Go

Основные блюда

Возможности платформыИнструментарий

Десерт

Очень субъективное мнение прожжёного “джависта”

МенюЗакуска

Краткий обзор синтаксиса Go

Основные блюда

Возможности платформыИнструментарий

Десерт

Очень субъективное мнение прожжёного “джависта”

Немного истории

2007 2009 2012 2013 2015

Начало

Опубликован исходной код

1.0 1.1 1.5

Где используется?

https://github.com/golang/go/wiki/GoUsers

Google, Docker, Heroku, Cloud Foundry, CoreOS, InfluxDB, Dropbox, OpenShift, SoundCloud, Toggl, etc.

Короче, в облаках

КритикаВо избежание завышеных ожиданий :)

“Can't reach the pedals. no brakes. gaining speed. eyes bulging in horror. technical debt crash eminent. “

— Tim Dysinger, @dysinger

Не достаёт до педалей. Нет тормозов. Набирает скорость. Глаза полны ужаса. Знаменит катастрофой технического долга

Paul Phillips @extempore2

“go is a terrible, terrible language, yet still a major productivity boost. Amdahl's law in another context.”

“You often see languages which are fighting the last war. Go is fighting the War of 1812.”

“reduce: what you will do with your expectations after you start with Go”

“Rust and Scala drown you in complexity. Go drowns you in simplicity.”

Paul Phillips @extempore2

Tour of Gotour.golang.org

package  main  

import  "fmt"  

func  main()  {     fmt.Println("Hello,  Devclub!")  }  

package  main  

import  "fmt"  

func  main()  {     fmt.Println("Hello,  Devclub!")  }  

Реакиця Java-программиста на названия функций с заглавной буквы

Чего нет?Нет наследования

Нет “генериков”

Нет классов

Нет перегрузки методов

Нет исключений

итд…

Нет “генериков” и нормальной обработки ошибок… КАК НА ЭТОМ ВООБЩЕ МОЖНО ЧТО-ТО ПИСАТЬ?!

Что же есть?

Функции

“Слайсы”

Структуры

Интерфейсы

Методы

Указатели

Го-рутины

Каналы

func  main()  {     fmt.Println("1  +  2  =",  add(1,  2))  }  

func  add(a  int,  b  int)  int  {     return  a  +  b  }

Функции

func  main()  {     fmt.Println("1  +  2  =",  add(1,  2))  }  

func  add(a  int,  b  int)  int  {     return  a  +  b  }

Функции

func  main()  {     fmt.Println("1  +  2  =",  add(1,  2))  }  

func  add(a,  b  int)  int  {     return  a  +  b  }

Функции

func  main()  {      s,  p  :=  calculate(1,  2)     fmt.Printf("1+2=%d,  1*2=%d",  s,  p)  }  

func  calculate(a,  b  int)  (int,  int)  {      return  a  +  b,  a  *  b  }

Функции

func  main()  {      s,  p  :=  calculate(1,  2)     fmt.Printf("1+2=%d,  1*2=%d",  s,  p)  }  

func  calculate(a,  b  int)  (int,  int)  {      return  a  +  b,  a  *  b  }

Функции

func  main()  {      s,  p  :=  calculate(1,  2)     fmt.Printf("1+2=%d,  1*2=%d",  s,  p)  }  

func  calculate(a,  b  int)  (s,  p  int)  {      s  :=  a  +  b      p  :=  a  *  b      return  }

Функции

func  main()  {      double  :=  func(a  int)  int  {            return  a  *  2      }     double(14)  }  

Функции как значения

func  main()  {      double  :=  factory()     double(14)  }  

func  factory()  func(a  int)  int  {      return  func(a  int)  int  {            return  a  *  2      }  }

Функции как значения

Массивыvar  a  [4]int  a[0]  =  1  i  :=  a[0]

http://blog.golang.org/go-slices-usage-and-internals

arr  :=  [2]string{"Foo",  "Bar"}

arr  :=  […]string{"Foo",  "Bar"}

Слайсы Slicesa  :=  []int{1,  2,  3}      //  [1  2  3]

Нет описания размерности

b  :=  append(a,  4,  5)    //  [1  2  3  4  5]c  :=  make(c,  3)              //  [0  0  0]d  :=  b[1:3]                      //  [2  3]e  :=  b[:3]                        //  [1  2  3]

Мапы Maps

  monthdays  :=  map[string]int{       "Jan":  31,  "Feb":  28,  "Mar":  31,       "Apr":  30,  "May":  31,  "Jun":  30,       "Jul":  31,  "Aug":  31,  "Sep":  30,       "Oct":  31,  "Nov":  30,  "Dec":  31,     }  

  for  month,  days  :=  range  monthdays  {       fmt.Println(month,  days)     }

Мапы Maps

  monthdays  :=  map[string]int{       "Jan":  31,  "Feb":  28,  "Mar":  31,       "Apr":  30,  "May":  31,  "Jun":  30,       "Jul":  31,  "Aug":  31,  "Sep":  30,       "Oct":  31,  "Nov":  30,  "Dec":  31,     }  

  for  month,  days  :=  range  monthdays  {       fmt.Println(month,  days)     }

Вот эта запятая - обязательна!

Мапы Maps

  monthdays  :=  map[string]int{       "Jan":  31,  "Feb":  28,  "Mar":  31,       "Apr":  30,  "May":  31,  "Jun":  30,       "Jul":  31,  "Aug":  31,  "Sep":  30,       "Oct":  31,  "Nov":  30,  "Dec":  31,     }  

  value,  ok  :=  monthdays["Jan"]    fmt.Println(value)    //    31      fmt.Println(ok)          //    true

Указатели

var  p  *int  

i  :=  42  p  =  &i    fmt.Println(*p)  *p  =  21  fmt.Println(i)

42

21

Указатели

var  p  *int  

i  :=  42  p  =  &i    fmt.Println(*p)  *p  =  21  fmt.Println(i)

Указатели

var  p  *int  

i  :=  42  p  =  &i    fmt.Println(*p)  *p  =  21  fmt.Println(i)

Нет арифметики указателей

Структурыtype  Vertex  struct  {      X  int      Y  int  }  

Структурыtype  Vertex  struct  {      X  int      Y  int  }  

func  main()  {      fmt.Println(Vertex{1,  2})  }

Методыtype  Vertex  struct  {      X  int      Y  int  }  

func  (v  Vertex)  Total()  int  {      return  v.X  +  v.Y  }

Методыtype  Vertex  struct  {      X  int      Y  int  }  

func  (v  Vertex)  Total()  int  {      return  v.X  +  v.Y  }

v  :=  Vertex{1,  2}  v.Total()

Интерфейсы

type  Entity  interface  {      Total()  int  }  

Интерфейсы

type  Entity  interface  {      Total()  int  }  

Vertex реализует Entity

func  (v  Vertex)  Total()  int  {      return  v.X  +  v.Y  }

Интерфейсы

v  :=  Vertex  {1,  2}  blah(v)

func  blah(e  Entity)  {        e.Total()  }

Интерфейсы

func  foo(x  interface{})  int  {        x.(Vertex).Total()  }

Интерфейсы

func  foo(x  interface{})  int  {        x.(Vertex).Total()  }

panic:  interface  conversion:  interface  is  main.Vertex2,  not  main.Vertex  

goroutine  1  [running]:  main.main()     main.go:25  +0xcd  exit  status  2  

foo(Vertex2{1,2})

A programmer had a problem. He thought to solve it with threads.

two Now problems. he has

Го-рутины

foo(Vertex2{1,2})

go  foo(Vertex2{1,2})

Обычный вызов функции

Функция вызвана как го-рутина

func  ready(w  string,  sec  int)  {     time.Sleep(time.Duration(sec)  *  time.Second)     fmt.Println(w,  "is  ready!")  }  

func  main()  {     go  ready("Tea",  2)     go  ready("Coffee",  1)     fmt.Println("I'm  waiting")     time.Sleep(5  *  time.Second)  }

I’m waiting Coffee is ready Tea is ready

Каналыci  :=  make(chan  int)  cs  :=  make(chan  string)  cf  :=  make(chan  interface{})

ci <- 1 ← послать 1 в канал ci i := <-ci ← принять int из канала ci

var  c  chan  int  

func  ready(w  string,  sec  int)  {     time.Sleep(time.Duration(sec)  *  time.Second)     fmt.Println(w,  "is  ready!”)      с  <-­‐  1  }  

func  main()  {     go  ready("Tea",  2)     go  ready("Coffee",  1)     fmt.Println("I'm  waiting")      <-­‐c      <-­‐c  }

var  done  =  make(chan  bool)  var  msgs  =  make(chan  int)  

func  produce()  {     for  i  :=  0;  i  <  10;  i++  {       msgs  <-­‐  i     }     done  <-­‐  true  }  

func  consume()  {     for  {       msg  :=  <-­‐msgs       println(msg)     }  }  

func  main()  {     go  produce()     go  consume()     <-­‐  done  }

var  done  =  make(chan  bool)  var  msgs  =  make(chan  int)  

func  produce()  {     for  i  :=  0;  i  <  10;  i++  {       msgs  <-­‐  i     }     done  <-­‐  true  }  

func  consume()  {     for  {       msg  :=  <-­‐msgs       println(msg)     }  }  

func  main()  {     go  produce()     go  consume()     <-­‐  done  }

Запустить  го-­‐рутины

var  done  =  make(chan  bool)  var  msgs  =  make(chan  int)  

func  produce()  {     for  i  :=  0;  i  <  10;  i++  {       msgs  <-­‐  i     }     done  <-­‐  true  }  

func  consume()  {     for  {       msg  :=  <-­‐msgs       println(msg)     }  }  

func  main()  {     go  produce()     go  consume()     <-­‐  done  }

Высылаем  значения

var  done  =  make(chan  bool)  var  msgs  =  make(chan  int)  

func  produce()  {     for  i  :=  0;  i  <  10;  i++  {       msgs  <-­‐  i     }     done  <-­‐  true  }  

func  consume()  {     for  {       msg  :=  <-­‐msgs       println(msg)     }  }  

func  main()  {     go  produce()     go  consume()     <-­‐  done  }

Получаем  и  выводим  значения

var  done  =  make(chan  bool)  var  msgs  =  make(chan  int)  

func  produce()  {     for  i  :=  0;  i  <  10;  i++  {       msgs  <-­‐  i     }     done  <-­‐  true  }  

func  consume()  {     for  {       msg  :=  <-­‐msgs       println(msg)     }  }  

func  main()  {     go  produce()     go  consume()     <-­‐  done  }

Готово!

Рабочее окружение

https://golang.org/doc/code.html#Workspaces

Рабочее окружение

Рабочее окружение

Инструментарий

• go (version, build, test, get, install, …)

• gofmt

• godoc

• Редакторы (vim, atom, IntelliJ IDEA)

Мой выбор

Чего не хватает?

Отладчик Плагин для IntelliJ IDEA - в разработке

Возможна работа с GDB, но лучше сразу умереть

Менеджер зависимостей Много разных решений, все кривые

-vendor в 1.5

Кросс-компиляция

http://dave.cheney.net/2015/03/03/cross-compilation-just-got-a-whole-lot-better-in-go-1-5

env GOOS=linux GOARCH=386 go build hello.go

1. Собрал на Mac OS X для Linux

2. Запустил бинарник без дополнительных библиотек на Linux

Тестированиеpackage  math  

func  Add(a,  b  int)  int  {     return  a  +  b  } package  math  

import  "testing"  

func  TestAdd(t  *testing.T){     if  Add(1,  3)  !=  4  {       t.Error("Expecting  4")     }  }  

Тестированиеpackage  math  

func  Add(a,  b  int)  int  {     return  a  +  b  } package  math  

import  "testing"  

func  TestAdd(t  *testing.T){     if  Add(1,  3)  !=  4  {       t.Error("Expecting  4")     }  }  

/usr/local/go/bin/go  test  -­‐v  ./...  -­‐run  ^TestAdd$  Testing  started  at  03:35  ...  ?         _/Users/anton/work-­‐src/mygo   [no  test  files]PASS  ok       _/Users/anton/work-­‐src/mygo/math   0.007s

“У меня вот другой вопрос - а опердени на Go писать то уже можно или им только стартапы да уставшие

программисты балуются ?”

Вопрос на миллион долларов

— Евгений Холодков Профессионально разрабатывает опердени уже много лет

Оперденьpackage  main  

import  "net/http"  

func  main()  {     panic(http.ListenAndServe(":8080",          http.FileServer(http.Dir("."))))  }  

JavaGo

Ресурсы

http://www.miek.nl/downloads/Go/Learning-Go-latest.pdfhttps://tour.golang.org

http://blog.golang.orghttp://golangshow.comhttp://4gophers.ru

https://www.youtube.com/playlist?list=PLMW8Xq7bXrG58Qk-9QSy2HRh2WVeIrs7e

https://www.youtube.com/channel/UCx9QVEApa5BKLw9r8cnOFEA

Gopher Academy:

dotGo:

@antonarhipovhttp://www.slideshare.net/arhan https://speakerdeck.com/antonarhipov