Какво трябва да направите до 24-ти декември
Какво ще върне recover(), ако го извикаме без да сме в състояние на паника?
nilКакво ще изведе този код:
x := []string{"a","b","c"}
for v := range x {
fmt.Println(v)
}
Какво прави go test ./...?
Какво е example test и как се прави такъв?
Example<нещо-с-главна-буква>//Output:..., който се проверява срещи стандартния изход на функциятаnetconn, err := net.Dial("tcp", "golang.org:80")
if err != nil {
// handle error
}
fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n")
status, err := bufio.NewReader(conn).ReadString('\n')func Dial(network, address string) (Conn, error)
net.Connnetwork аргумента и връща правилният тип Connnet.Listener (интерфейс)Acceptnet.Conn за всяка връзка към сървъра виln, err := net.Listen("tcp", ":8080")
if err != nil {
// handle error
}
for {
conn, err := ln.Accept()
if err != nil {
// handle error
}
go handleConnection(conn)
}net/httppackage main
import ( "fmt" "net/http" ) func main() { resp, err := http.Get("http://fmi.golang.bg/") if err != nil { fmt.Println(err) return } fmt.Printf("GET fmi golang site said HTTP %d\n", resp.StatusCode) }
http.Request и http.Client може да се правят и по-сложни заявкиtype Request struct {
// Method specifies the HTTP method (GET, POST, PUT, etc.).
Method string
// URL specifies either the URI being requested or the URL to access.
URL *url.URL
// A header maps request lines to their values.
Header Header
// И доста други полета, за някои от които ще разкажем след малко...
}Get, Head, Post и PostForm за улеснениеDo(req *Request) (resp *Response, err error)
Чрез атрибутите на http.Client имате възможност да определите:
Transport ще се използва (пр. да зададете proxy)Status, Header, Body и др.
Тялото на отговора може да се чете от Body (io.ReadCloser):
package main
import (
"fmt"
"html"
"io/ioutil"
"log"
"net/http"
)
func main() { go http.ListenAndServe(":8282", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %s", html.EscapeString(r.URL.Path)) })) res, err := http.Get("http://localhost:8282/world") if err != nil { log.Fatal(err) } contents, err := ioutil.ReadAll(res.Body) res.Body.Close() if err != nil { log.Fatal(err) } fmt.Printf("Server responded with: %s", contents) }
http.Request се използва и за получаването на клиентски заявкиerr := req.ParseForm()
// handle if err != nil
sortOrder := req.Form.Get("sortby")Повече от един начин да одереш котка:
Request.Form от тип url.ValuesRequest.PostForm от тип url.ValuesRequest.Body от тип io.ReadCloserRequest.MultipartForm от тип *multipart.Form, след извикване на ParseMultipartForm()type ResponseWriter interface {
// Header returns the header map that will be sent by WriteHeader.
Header() Header
// Write writes the data to the connection as part of an HTTP reply.
Write([]byte) (int, error)
// WriteHeader sends an HTTP response header with status code.
WriteHeader(int)
}io.Writer интерфейсаТова ни позволява да си използваме неща като:
fmt.Fprintf(rw, "Нещо си")
за да отговаряме на HTTP заявки...
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}http.HandlerFunc, за който горният интерфейс е имплементиран:type HandlerFunc func(ResponseWriter, *Request)
http.HandleFunc добавя ново правило в http.DefaultServeMuxhttp.ServeMux е проста имплементация, която само match-ва пътя на заявкатаhttp.NotFoundHandlerNotFoundHandler - връща 404 и съобщениеTimeoutHandler - приема друг хендлър и лимитира времето за отговорFileServer - лесен файлов сървърRedirectHandlerStripPrefix - премахва част от пътя преди да предаде заявка на подаден хендлърServeMux също е handlerpackage main
import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
"time"
)
func main() { mux := http.NewServeMux() mux.Handle("/doc/", http.FileServer(http.Dir("/usr/share/"))) mux.Handle("/google/", http.RedirectHandler("https://www.google.com", http.StatusTemporaryRedirect)) mux.Handle("/proxy/", http.StripPrefix("/proxy/", httputil.NewSingleHostReverseProxy( &url.URL{Scheme: "https", Host: "mirrors.kernel.org", Path: "/"}, ))) mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { if req.URL.Path == "/" { fmt.Fprintf(w, "Welcome to the jungle!") return } http.NotFound(w, req) }) s := &http.Server{Addr: ":8282", Handler: mux, WriteTimeout: 1 * time.Second} log.Printf("Starting server on %s", s.Addr) log.Fatal(s.ListenAndServe()) }
ResponseWriter е базов интерфейс, но в някои ситуации ви се налага да имате повече контрол:
type CloseNotifier interface {
// CloseNotify returns a channel that receives a single value
// when the client connection has gone away.
CloseNotify() <-chan bool
}
type Hijacker interface {
// Hijack lets the caller take over the connection.
// After a call to Hijack(), the HTTP server library
// will not do anything else with the connection.
Hijack() (net.Conn, *bufio.ReadWriter, error)
}
http.RoundTripper е абстракцията за изпълнение на единична HTTP request-response транзакция:
type RoundTripper interface {
RoundTrip(*Request) (*Response, error)
}
http.Transport е имплементация на http.RoundTripper, която поддръжа HTTP, HTTPS и проксита. По подразбиране в http пакета имаме:
var DefaultTransport RoundTripper = &Transport{
Proxy: ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
}httputil и httptest с благинкиhttptest има вградени ResponseRecorder и Server имплементации за брутално лесни HTTP end-to-end тестовеhttp.Handle("/index.html", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// server push is available if w implements http.Pusher
if p, ok := w.(http.Pusher); ok {
p.Push("/static/gopher.png", nil}
}
// load the main page
w.Header().Set("Content-Type", "text/html")
w.Write([]byte(`<img src="/static/gopher.png" />`))
}))Темплейт:
<h1>Editing {{.Title}}</h1>
<form action="/save/{{.Title}}" method="POST">
<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body}}</textarea></div>
<div><input type="submit" value="Save"></div>
</form>Изполването му:
func editHandler(w http.ResponseWriter, r *http.Request) {
p := &Page{
Title: "Hello, world!",
Body: "Lorem ipsum dolor sit amet...",
}
t, _ := template.ParseFiles("edit.html")
t.Execute(w, p)
}
text/template
import "text/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
Hello, <script>alert('you have been pwned')</script>!
html/template
import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
Hello, <script>alert('you have been pwned')</script>!html/template се грижи всичко да е правилно escape-натоContext {{.}} After
{{.}} O'Reilly: How are <i>you</i>?
<a title='{{.}}'> O'Reilly: How are you?
<a href="/{{.}}"> O'Reilly: How are %3ci%3eyou%3c/i%3e?
<a href="?q={{.}}"> O'Reilly%3a%20How%20are%3ci%3e...%3f
<a onx='f("{{.}}")'> O\x27Reilly: How are \x3ci\x3eyou...?
<a onx='f({{.}})'> "O\x27Reilly: How are \x3ci\x3eyou...?"
<a onx='pattern = /{{.}}/;'> O\x27Reilly: How are \x3ci\x3eyou...\x3fНяколко библиотеки, които ще улеснят живота ви по темата
golang.org/x/net/contextcontext от стандартната библиотека е малко различен