Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "Пишем функциональное, надежное и быстрое веб-приложение на Go"— 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 системы
Время сборки Эффективность Масштабируемость 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() 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() 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() go io.Copy(c, c)

13 Сoncurrency Горутины: go doFoo(a, b) go conn.Handle() go func() { }()
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): } 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() 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) { delete(clients, c)

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(` <html> <body> <b>Hi, {{.Name}}!</b> <form> <input type="text" id="chattext"></input> <input type="button" value="Say" onclick="sendMessage()"></input> </form> <textarea readonly=1 rows=20 id="alltext"></textarea> </body> </html> `))

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 Что дальше? http://golang.org http://tour.golang.org golang-nuts@
Книги: 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"

Similar presentations


Ads by Google