Presentation is loading. Please wait.

Presentation is loading. Please wait.

Пишем функциональное, надежное и быстрое веб- приложение на Go Дмитрий Вьюков, Google.

Similar presentations


Presentation on theme: "Пишем функциональное, надежное и быстрое веб- приложение на Go Дмитрий Вьюков, Google."— Presentation transcript:

1 Пишем функциональное, надежное и быстрое веб- приложение на Go Дмитрий Вьюков, Google

2 План Зачем новый язык? Привет, Мир! Пишем веб-приложение Инструментарий

3 История Конец 2007: Rob Pike, Ken Thompson и RobertGriesemer начали проектировать Ноябрь 2009: open-source release Март 2012: релиз Go1 Go1.1, Go1.2, Go1.3

4 Зачем? Дизайн мотивирован нашими нуждами в Google: Large-scale системы Large-scale разработка Время сборки Эффективность Масштабируемость Concurrency Безопасность

5 Что такое Go? Простой язык, который легко изучить и читать Статически-типизированный, но “чувствуется” как динамический Компилируется в машинный код, но быстрая разработка Быстрый и масштабируемый Сборка мусора Встроенная поддержка concurrency Стандартная библитека “с включенными батарейками” Open-source (400+ контрибьюторов)

6 Кто использует? Google: dl.google.co Google: vitess (MySQL scaling) Google: flywheel (mobile proxy) BBC Worldwide Canonical Heroku Nokia SoundCloud Apple Yandex BitBucket dotCloud github gov.uk Heroku Intel Iron.io Mozilla Percona Zynga Docker Packer

7 Крэш-курс

8 Привет, Мир! package main import "fmt" func main() { fmt.Printf("Привет, Мир!\n") }

9 Привет, Net! func main() { ln, err := net.Listen("tcp", "localhost:11500") if err != nil { log.Fatal(err) } for { c, err := ln.Accept() if err != nil { log.Fatal(err) } fmt.Fprintf(c, "Привет, Net!\n") c.Close() }

10 Интерфейсы fmt.Fprintf(c, "Привет, Net!\n") Duck typing! type Writer interface { Write(p []byte) (n int, err error) } type netFD struct {...} func (fd *netFD) Write(p []byte) (nn int, err error)

11 Эхо-сервер func main() { ln, err := net.Listen("tcp", "localhost:11500") if err != nil { log.Fatal(err) } for { c, err := ln.Accept() if err != nil { log.Fatal(err) } io.Copy(c, c) }

12 Привет, concurrency! func main() { ln, err := net.Listen("tcp", "localhost:11500") if err != nil { log.Fatal(err) } for { c, err := ln.Accept() if err != nil { log.Fatal(err) } go io.Copy(c, c) }

13 Сoncurrency Горутины: go doFoo(a, b) go conn.Handle() go func() { doFoo(a, b) notifyCompletion() }()

14 Channels Каналы: c := make(chan int) c <- 42 fmt.Println(<-c)

15 Select select { case inChan <- v: fmt.Println("Отправлено") case <-timeoutChan: fmt.Println("Потрачено") }

16 Запрос нескольких бэкендов func multiGet(urls []string) (results []*http.Response) { res := make(chan *http.Response) for _, url := range urls { go func(url string) { resp, _ := http.Get(url) res <- resp }(url) } for _ = range urls { results = append(results, <-res) } return }

17 Запрос с таймаутом t := time.After(time.Second) for _ = range urls { select { case resp := <-res: results = append(results, resp) case <-t: return }

18 Файловер func getFailover(primary, secondary string) *http.Response { res := make(chan *http.Response, 1) go func() { res <- requestServer(primary) }() select { case resp := <-res: return resp case <-time.After(50 * time.Millisecond): } go func() { res <- requestServer(secondary) }() return <-res }

19 Батарейки включены encoding/{json, xml, gob, base64} compress/{gzip, bzip2, flate} crypto/{aes, des, sha1, tls, x509} net/{http, rpc, smtp} database/sql html/template regexp flag

20 В бой!

21 Флаги package main import "flag" var ( httpAddr = flag.String("http", ":8080", "address to serve http") apiAddr = flag.String("api", ":8081", "address to serve api") ) func main() { flag.Parse()...

22 HTTP сервер import "net/http" func main() {... http.HandleFunc("/", handleWelcome) http.HandleFunc("/chat", handleChat) go http.ListenAndServe(*httpAddr, nil)...

23 Websocket сервер import "code.google.com/p/go.net/websocket" func main() {... http.Handle("/ws", websocket.Handler(handleWebsocket))...

24 API сервер import "net" func main() {... ln, err := net.Listen("tcp", *apiAddr) if err != nil { log.Fatal(err) } go func() { for { c, err := ln.Accept() if err != nil { log.Fatal(err) } go handleApi(c) } }()

25 Бизнес логика type Message struct { From string Text string } type Client interface { Send(m Message) } var ( clients = make(map[Client]bool) clientsMutex sync.Mutex )

26 Бизнес логика (2) func registerClient(c Client) { clientsMutex.Lock() clients[c] = true clientsMutex.Unlock() } func unregisterClient(c Client) { clientsMutex.Lock() delete(clients, c) clientsMutex.Unlock() }

27 Бизнес логика (3) func broadcastMessage(m Message) { clientsMutex.Lock() for c := range clients { c.Send(m) } clientsMutex.Unlock() }

28 HTML шаблоны var chatPageTempl = template.Must(template.New("").Parse(` Hi, {{.Name}}! `))

29 HTTP обработчики func handleChat(w http.ResponseWriter, r *http.Request) { name := r.FormValue("name") log.Printf("serving chat page for '%v'", name) type Params struct { Name string } chatPageTempl.Execute(w, &Params{name}) }

30 Websocket обработчик type WSClient struct { conn *websocket.Conn enc *json.Encoder } func (c *WSClient) Send(m Message) { c.enc.Encode(m) }

31 Websocket обработчик (2) func handleWebsocket(ws *websocket.Conn) { c := &WSClient{ws, json.NewEncoder(ws)} registerClient(c) dec := json.NewDecoder(ws) for { var m Message if err := dec.Decode(&m); err != nil { log.Printf("error reading from websocket: %v", err) break } broadcastMessage(m) } unregisterClient(c) }

32 Демо

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

34 Сборка Нулевая конфигурация, нет MAKEFILE $ go run myprog.go $ go build myprog $ go get code.google.com/p/go.new/websocket

35 Пишем код $ go fmt mysource.go $ go vet - статический анализ кода $ godoc - документация goimports/gocode/oracle: поддержка IDE

36 Тестируем $ go test $ go test -cover $ go test -race Информативные крэш-репорты

37 Оптимизируем $ go test -bench $ go test -bench -cpu=1,2,4 $ go test -benchmem $ go test -cpuprofile $ go test -memprofile $ go test -blockprofile

38 Оптимизируем (2) - Профайлер горутин - Трейсер GC - Трейсер планировщика - Трейсер аллокатора памяти - Статистика аллокатора памяти - Дамп кучи

39 Мониторинг import "expvar" var ( expMsgRecv = expvar.NewInt("msg_recv") expMsgSend = expvar.NewInt("msg_send") ) func broadcastMessage(m Message) {... expMsgRecv.Add(1) expMsgSend.Add(int64(len(clients))) }

40 Что дальше? Книги: An Introduction to Programming in Go Network Programming with Go Programming in Go: Creating Applications for the 21st Century

41 Другие доклады по Go 16:35 Common: Go: аналитика Рунета в реальном времени 17:45 Python: Go на Google App Engine - просто, надёжно, быстро и недорого. 19:30 Python: Juju и MaaS - эффективные инструменты развёртывания масштабных систем на "железе" и в "облаках".

42 Q&A Спасибо! Дмитрий Вьюков,


Download ppt "Пишем функциональное, надежное и быстрое веб- приложение на Go Дмитрий Вьюков, Google."

Similar presentations


Ads by Google