понедельник, 31 августа 2020 г.

Пакет strings в Golang, функция Compare

func Compare(a, b string) int

Compare возвращает целое число, сравнивая две строки лексикографически. Результатом будет 0, если a == b, -1, если a < b, и +1, если a > b.

Compare включена только для симметрии с пакетом bytes. Обычно проще и быстрее использовать встроенные операторы сравнения строк ==, <, > и так далее.

Пример использования Compare

package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(strings.Compare("a", "b"))
    fmt.Println(strings.Compare("a", "a"))
    fmt.Println(strings.Compare("b", "a"))
}

Вывод:

-1
0
1

В подтверждение слов о том, что функция реализована только для симмертрии с пакетом bytes, взглянем на реализацию функции в пакете strings:

package strings

func Compare(a, b string) int {
    if a == b {
      return 0
    }
    if a < b {
      return -1
    }
    return +1
}

Как видно из кода - функция внутри сама использует операторы == и <.


Читайте также:


четверг, 27 августа 2020 г.

Пакет pprof в Golang

Пакет pprof обслуживает данные профилирования среды выполнения HTTP-сервера в формате, ожидаемом инструментом визуализации pprof.

Пакет обычно импортируется только из-за побочного эффекта регистрации его обработчиков HTTP. Все обрабатываемые пути начинаются с /debug/pprof/.

Чтобы использовать pprof, свяжите этот пакет со своей программой:

import _ "net/http/pprof"

Если ваше приложение еще не запустило http-сервер, вам необходимо запустить его. Добавьте "net/http" и "log" к вашему импорту и следующий код к вашей main функции:

go func() {
    log.Println(http.ListenAndServe("localhost:6060", nil))
}()

Если вы не используете DefaultServeMux, вам нужно будет зарегистрировать обработчики в используемом мультиплексоре (mux). Например:

package main

import (
    "log"
    "net/http"
    "net/http/pprof"
)

func main() {
    mux := http.NewServeMux()

    // Здесь можно указать свой путь
    mux.HandleFunc("/debug/pprof/profile", pprof.Profile)

    log.Fatal(http.ListenAndServe(":6060", mux))
}

Затем используйте инструмент pprof, чтобы посмотреть профиль кучи (heap profile):

go tool pprof http://localhost:6060/debug/pprof/heap

Или посмотреть 30-секундный профиль процессора:

go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30

Или посмотреть профиль блокировки goroutine после вызова runtime.SetBlockProfileRate в вашей программе:

go tool pprof http://localhost:6060/debug/pprof/block

Или посмотреть на держателей конкурирующих мьютексов после вызова runtime.SetMutexProfileFraction в вашей программе:

go tool pprof http://localhost:6060/debug/pprof/mutex

Пакет также экспортирует обработчик, который обслуживает данные трассировки выполнения для команды "go tool trace". Чтобы собрать 5-секундную трассировку выполнения:

wget -O trace.out http://localhost:6060/debug/pprof/trace?seconds=5
go tool trace trace.out

Чтобы просмотреть все доступные профили, откройте в браузере http://localhost:6060/debug/pprof/.

Функция Cmdline

func Cmdline(w http.ResponseWriter, r *http.Request)

Cmdline отвечает командной строкой запущенной программы с аргументами, разделенными NUL байтами. Инициализация пакета регистрирует его как /debug/pprof/cmdline.

Функция Handler

func Handler(name string) http.Handler

Handler возвращает обработчик HTTP, который обслуживает именованный профиль.

Функция Index

func Index(w http.ResponseWriter, r *http.Request)

Index отвечает профилем в формате pprof, указанным в запросе. Например, "/debug/pprof/heap" обслуживает профиль "heap". Index отвечает на запрос "/debug/pprof/" HTML-страницей со списком доступных профилей.

Функция Profile

func Profile(w http.ResponseWriter, r *http.Request)

Profile отвечает профилем процессора в формате pprof. Профилирование длится в течение времени, указанного в параметре GET в секундах, или 30 секунд, если не указано иное. Инициализация пакета регистрирует его как /debug/pprof/profile.

Функция Symbol

func Symbol(w http.ResponseWriter, r *http.Request)

Symbol ищет программные счетчики, перечисленные в запросе, отвечая таблицей, отображающей программные счетчики на имена функций. Инициализация пакета регистрирует его как /debug/pprof/symbol.

Функция Trace

func Trace(w http.ResponseWriter, r *http.Request)

Trace отвечает трассировкой выполнения в двоичной форме. Трассировка длится в течение времени, указанного в параметре GET в секундах, или в течение 1 секунды, если не указано иное. Инициализация пакета регистрирует его как /debug/pprof/trace.


Читайте также:


суббота, 22 августа 2020 г.

Пакет httptrace в Golang

Пакет httptrace предоставляет механизмы для отслеживания событий в клиентских HTTP-запросах.

Пример использования httptrace

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/http/httptrace"
)

func main() {
    req, _ := http.NewRequest("GET", "http://example.com", nil)
    trace := &httptrace.ClientTrace{
        GotConn: func(connInfo httptrace.GotConnInfo) {
            fmt.Printf("Got Conn: %+v\n", connInfo)
        },
        DNSDone: func(dnsInfo httptrace.DNSDoneInfo) {
            fmt.Printf("DNS Info: %+v\n", dnsInfo)
        },
    }
    req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
    _, err := http.DefaultTransport.RoundTrip(req)
    if err != nil {
        log.Fatal(err)
    }
}

Функция WithClientTrace

func WithClientTrace(ctx context.Context, trace *ClientTrace) context.Context

WithClientTrace возвращает новый контекст на основе предоставленного родительского ctx. Запросы клиента HTTP, сделанные с возвращенным контекстом, будут использовать предоставленные перехватчики трассировки в дополнение к любым предыдущим перехватчикам, зарегистрированным с помощью ctx. Любые хуки, определенные в предоставленной трассировке, будут вызываться первыми.

Тип ClientTrace

ClientTrace - это набор перехватчиков для запуска на различных этапах исходящего HTTP-запроса. Любой конкретный хук может быть nil. Функции могут вызываться одновременно из разных goroutines, а некоторые из них могут вызываться после завершения или сбоя запроса.

ClientTrace в настоящее время отслеживает один HTTP-запрос и ответ в течение одного цикла и не имеет перехватчиков, которые охватывают серию перенаправленных запросов.

type ClientTrace struct {
    // GetConn вызывается 
    // перед созданием соединения или
    // извлекается из неактивного пула. 
    // hostPort - это "host:port" 
    // цели или прокси. 
    // GetConn называется даже
    // если уже доступно незанятое 
    // кэшированное соединение.
    GetConn func(hostPort string)

    // GotConn вызывается после 
    // успешного получения подключения.
    // Нет никакого хука 
    // для неуспешного получения соединения; 
    // вместо этого используйте ошибку из 
    // Transport.RoundTrip.
    GotConn func(GotConnInfo)

    // PutIdleConn вызывается, 
    // когда соединение возвращается в пул ожидания.
    // Если err равен nil, соединение было
    // успешно возвращено в пул ожидания. 
    // Если err не равно nil, объясняет, почему нет. 
    // PutIdleConn не вызывается, если
    // повторное использование соединения 
    // отключено через Transport.DisableKeepAlives.
    // PutIdleConn вызывается до 
    // возврата вызов Response.Body.Close.
    // Для HTTP/2 этот хук в настоящее время не используется.
    PutIdleConn func(err error)

    // GotFirstResponseByte вызывается, 
    // когда первый байт заголовков ответа доступен.
    GotFirstResponseByte func()

    // Got100Continue вызывается, 
    // если сервер отвечает "100 Continue"
    Got100Continue func()

    // Got1xxResponse вызывается для каждого 
    // информационного заголовка ответа 1xx
    // возвращается перед окончательным ответом, 
    // отличным от 1xx. Got1xxResponse называется
    // для ответов "100 Continue", 
    // даже если также определено Got100Continue.
    // Если он возвращает ошибку, 
    // клиентский запрос прерывается с этим значением ошибки.
    Got1xxResponse func(code int, header textproto.MIMEHeader) error // Go 1.11

    // DNSStart вызывается, когда начинается поиск DNS.
    DNSStart func(DNSStartInfo)

    // DNSDone вызывается по окончании поиска DNS.
    DNSDone func(DNSDoneInfo)

    // ConnectStart вызывается, 
    // когда начинается Dial нового соединения.
    // Если net.Dialer.DualStack 
    // (IPv6 "Happy Eyeballs") поддержка
    // включена, ConnectStart можно вызывать несколько раз.
    ConnectStart func(network, addr string)

    // ConnectDone вызывается 
    // когда Dial нового соединения завершается. 
    // Предоставленная err указывает,
    // успешно ли соединение завершено.
    // Если поддержка net.Dialer.DualStack ("Happy Eyeballs")
    // включена, ConnectDone можно вызывать несколько раз.
    ConnectDone func(network, addr string, err error)

    // TLSHandshakeStart вызывается, 
    // когда начинается рукопожатие TLS.
    // Когда подключаемся к HTTPS-сайту 
    // через HTTP-прокси, рукопожатие происходит 
    // после того, как запрос CONNECT обработан прокси.
    TLSHandshakeStart func() // Go 1.8

    // TLSHandshakeDone вызывается 
    // после TLS рукопожатие 
    // с успешным статусом соединения 
    // при успешном рукопожатии или 
    // есть ошибка, отличная от nil при сбое рукопожатия.
    TLSHandshakeDone func(tls.ConnectionState, error) // Go 1.8

    // WroteHeaderField вызывается 
    // после того, как Transport записал
    // заголовок каждого запроса. 
    // Во время этого вызова значения
    // могут быть буферизованы и еще не записаны в сеть.
    WroteHeaderField func(key string, value []string) // Go 1.11

    // WroteHeaders вызывается 
    // после того, как Transport записал
    // все заголовки запроса.
    WroteHeaders func()

    // Wait100Continue вызывается, если указан запрос
    // "Expect: 100-continue", и Transport записал
    // заголовки запроса, но ожидает "100 Continue" от
    // сервера перед записью тела запроса.
    Wait100Continue func()

    // WroteRequest вызывается с результатом записи
    // запроса и любого тела. Может вызываться несколько раз
    // в случае повторных запросов.
    WroteRequest func(WroteRequestInfo)
}

Функция ContextClientTrace

func ContextClientTrace(ctx context.Context) *ClientTrace

ContextClientTrace возвращает ClientTrace, связанный с предоставленным контекстом. Если нет, возвращается nil.

Тип DNSDoneInfo

DNSDoneInfo содержит информацию о результатах поиска DNS.

type DNSDoneInfo struct {
    // Addrs - это адреса IPv4 и/или IPv6, 
    // найденные в DNS поиске. 
    // Содержимое среза не должно изменяться.
    Addrs []net.IPAddr

    // Err - это любая ошибка, 
    // произошедшая во время поиска DNS.
    Err error

    // Coalesced флаг true если Addrs 
    // совместно использованы с другим вызывающим абонентом, 
    // который одновременно выполнял такой же поиск DNS.
    Coalesced bool
}

Тип DNSStartInfo

DNSStartInfo содержит информацию о DNS-запросе.

type DNSStartInfo struct {
    Host string
}

Тип GotConnInfo

GotConnInfo является аргументом функции ClientTrace.GotConn и содержит информацию о полученном соединении.

type GotConnInfo struct {
    // Conn - это полученное соединение. 
    // Оно принадлежит http.Transport 
    // и его нельзя читать, писать или
    // закрыть пользователями ClientTrace.
    Conn net.Conn

    // Reused равен true если это соединение
    // было ранее использовано для другого HTTP-запроса.
    Reused bool

    // WasIdle - было ли это соединение получено из
    // пула ожидания.
    WasIdle bool

    // IdleTime сообщает, 
    // сколько времени соединение 
    // ранее было бездействующим, 
    // если WasIdle истинно.
    IdleTime time.Duration
}

Тип WroteRequestInfo

WroteRequestInfo содержит информацию, предоставленную хуку WroteRequest.

type WroteRequestInfo struct {
    // Err - это любая ошибка, обнаруженная при записи запроса.
    Err error
}


Читайте также:


вторник, 18 августа 2020 г.

Пакет httptest в Golang

Пакет httptest предоставляет утилиты для тестирования HTTP.

Функция NewRequest

func NewRequest(method, target string, body io.Reader) *http.Request

NewRequest возвращает новый входящий Request сервера, подходящий для передачи http.Handler для тестирования.

target является RFC 7230 "request-target": это может быть либо путь, либо абсолютный URL. Если target является абсолютный URL-адрес, используется имя хоста из URL-адреса. В противном случае используется example.com.

В поле TLS устанавливается фиктивное значение, отличное от nil, если target имеет схему "https".

Request.Proto всегда HTTP/1.1.

Пустой method означает "GET".

Предоставленное body может быть nil. Если тело имеет тип *bytes.Reader, *strings.Reader или *bytes.Buffer, устанавливается Request.ContentLength.

NewRequest паникует при ошибке для простоты использования при тестировании, где паника допустима.

Чтобы сгенерировать клиентский HTTP-запрос вместо запроса сервера, используйте функцию NewRequest в пакете net/http.

Тип ResponseRecorder

ResponseRecorder - это реализация http.ResponseWriter, которая записывает его изменения для последующей проверки в тестах.

type ResponseRecorder struct {
    // Code - это код ответа HTTP, 
    // установленный WriteHeader.
    //
    // Обратите внимание, что если Handler 
    // никогда не вызывает WriteHeader или Write,
    // Code может оказаться 0, 
    // а не неявным http.StatusOK. 
    // Чтобы получить неявное значение, 
    // используйте метод Result.
    Code int

    // HeaderMap содержит заголовки, 
    // явно установленные Handler.
    // Это внутренняя деталь.
    //
    // Не рекомендуется: 
    // HeaderMap существует для исторической совместимости
    // и не должны использоваться. 
    // Чтобы получить доступ к заголовкам, 
    // возвращаемым обработчиком,
    // использовать карту Response.Header, 
    // возвращенную методом Result.
    HeaderMap http.Header

    // Body - это буфер, 
    // в который отправляются вызовы Write Handler'а.
    // Если nil, Writes игнорируется.
    Body *bytes.Buffer

    // Flushed, флаг вызвал ли Handler Flush.
    Flushed bool
    // содержит отфильтрованные или неэкспортированные поля
}

Пример использования NewRequest, NewRecorder

package main

import (
    "fmt"
    "io"
    "io/ioutil"
    "net/http"
    "net/http/httptest"
)

func main() {
    handler := func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "<html><body>Hello World!</body></html>")
    }

    req := httptest.NewRequest("GET", "http://example.com/foo", nil)
    w := httptest.NewRecorder()
    handler(w, req)

    resp := w.Result()
    body, _ := ioutil.ReadAll(resp.Body)

    fmt.Println(resp.StatusCode)
    fmt.Println(resp.Header.Get("Content-Type"))
    fmt.Println(string(body))

}

Вывод:

200
text/html; charset=utf-8
<html><body>Hello World!</body></html>

Тип Server

Server - это HTTP-сервер, который прослушивает выбранный системой порт на локальном интерфейсе обратной связи для использования в сквозных (end-to-end) HTTP-тестах.

type Server struct {
    // базовый URL формы 
    // http://ipaddr:port без слеша в конце
    URL      string 
    Listener net.Listener

    // EnableHTTP2 контролирует, включен ли HTTP/2
    // на сервере. Он должен быть установлен между вызовами
    // NewUnstartedServer и Server.StartTLS.
    EnableHTTP2 bool // Go 1.14

    // TLS - это необязательная конфигурация TLS, 
    // заполненная новой конфигурацией после запуска TLS. 
    // Если установлено на 
    // не запущенном сервере до вызова StartTLS,
    // существующие поля копируются в новый конфиг.
    TLS *tls.Config

    // Config может быть изменен 
    // после вызова NewUnstartedServer и
    // перед Start или StartTLS.
    Конфиг *http.Server
    // содержит отфильтрованные или неэкспортированные поля
}

Пример использования Server

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httptest"
)

func main() {
    ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello, client")
    }))
    defer ts.Close()

    res, err := http.Get(ts.URL)
    if err != nil {
        log.Fatal(err)
    }
    greeting, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s", greeting)
}

Вывод:

Hello, client

Пример использования Server (HTTP2)

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httptest"
)

func main() {
    ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, %s", r.Proto)
    }))
    ts.EnableHTTP2 = true
    ts.StartTLS()
    defer ts.Close()

    res, err := ts.Client().Get(ts.URL)
    if err != nil {
        log.Fatal(err)
    }
    greeting, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s", greeting)

}

Вывод:

Hello, HTTP/2.0

Функция NewServer

func NewServer(handler http.Handler) *Server

NewServer запускается и возвращает новый Server. По завершении вызывающий должен вызвать Close, чтобы закрыть его.

Функция NewTLSServer

func NewTLSServer(handler http.Handler) *Server

NewTLSServer запускается и возвращает новый Server с использованием TLS. По завершении вызывающий должен вызвать Close, чтобы закрыть его.

Пример использования NewTLSServer

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httptest"
)

func main() {
    ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello, client")
    }))
    defer ts.Close()

    client := ts.Client()
    res, err := client.Get(ts.URL)
    if err != nil {
        log.Fatal(err)
    }

    greeting, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s", greeting)
}

Вывод:

Hello, client


Читайте также:


суббота, 15 августа 2020 г.

Релиз Go 1.15, основная библиотека

Новый встроенный пакет tzdata

Go 1.15 включает новый пакет time/tzdata, который позволяет встраивать базу данных часовых поясов в программу. Импорт этого пакета (как import _ "time/tzdata") позволяет программе находить информацию о часовом поясе, даже если база данных часовых поясов недоступна в локальной системе. Вы также можете встроить базу данных часовых поясов, создав с помощью -tags timetzdata. При любом подходе размер программы увеличивается примерно на 800 КБ.

Cgo

Go 1.15 преобразует C-тип EGLConfig в Go-тип uintptr. Это изменение аналогично тому, как Go 1.12 и новее обрабатывает типы EGLDisplay, Darwin CoreFoundation и Java JNI.

Прекращение поддержки X.509 CommonName

Устаревшее поведение, заключающееся в обработке поля CommonName в сертификатах X.509 как имени хоста при отсутствии альтернативных имен субъектов, теперь по умолчанию отключено. Его можно временно снова включить, добавив значение x509ignoreCN=0 в переменную среды GODEBUG.

Обратите внимание, что если CommonName является недопустимым именем хоста, оно всегда игнорируется, независимо от настроек GODEBUG. К недопустимым именам относятся имена с любыми символами, кроме букв, цифр, дефисов и подчеркиваний, а также имена с пустыми метками или конечными точками.

Незначительные изменения в библиотеке

Как всегда, в библиотеку внесены различные незначительные изменения и обновления, сделанные с учетом обещания совместимости с Go 1.

bufio

Когда Scanner используется с недопустимым io.Reader, который неправильно возвращает отрицательное число из Read, Scanner больше не паникует, а вместо этого вернет новую ошибку ErrBadReadCount.

context

Создание производного Context с использованием родительского nil элемента теперь явно запрещено. Любая попытка сделать это с помощью функций WithValue, WithDeadline или WithCancel вызовет панику.

crypto

Типы PrivateKey и PublicKey в пакетах crypto/rsa, crypto/ecdsa и crypto/ed25519 теперь имеют метод Equal для сравнения ключей на эквивалентность или для создания интерфейсов с типобезопасностью для публичных ключей. Сигнатура метода совместима с определением равенства go-cmp.

Hash теперь реализует fmt.Stringer.

crypto/ecdsa

Новые функции SignASN1 и VerifyASN1 позволяют генерировать и проверять подписи ECDSA в стандартной кодировке DER ASN.1.

crypto/elliptic

Новые функции MarshalCompressed и UnmarshalCompressed позволяют кодировать и декодировать точки эллиптических кривых NIST в сжатом формате.

crypto/rsa

VerifyPKCS1v15 теперь отклоняет недопустимые короткие подписи с отсутствующими ведущими нулями в соответствии с RFC 8017.

crypto/tls

Новый тип Dialer и его метод DialContext позволяют использовать контекст как для подключения, так и для обмена рукопожатиями с сервером TLS.

Новый обратный вызов VerifyConnection для типа Config позволяет настраивать логику проверки для каждого соединения. Он имеет доступ к ConnectionState, который включает сертификаты одноранговых узлов (peer certificates), SCT и сшитые ответы OCSP.

Автоматически сгенерированные ключи билета сеанса теперь автоматически меняются каждые 24 часа со сроком действия 7 дней, чтобы ограничить их влияние на прямую секретность.

Время жизни сеансового билета в TLS 1.2 и более ранних версиях, где ключи сеанса повторно используются для возобновленных подключений, теперь ограничено 7 днями, чтобы ограничить их влияние на прямую секретность.

Проверки защиты от перехода на более раннюю версию на стороне клиента, указанные в RFC 8446, теперь применяются. Это может вызвать ошибки подключения для клиентов, сталкивающихся с промежуточными ящиками, которые ведут себя как атаки с несанкционированным переходом на более раннюю версию.

SignatureScheme, CurveID и ClientAuthType теперь реализуют fmt.Stringer.

Поля ConnectionState OCSPResponse и SignedCertificateTimestamps теперь повторно заполняются для возобновленных подключений на стороне клиента.

tls.Conn теперь возвращает непрозрачную ошибку при постоянно разорванных соединениях, оборачивая временную net.Error. Чтобы получить доступ к исходной net.Error, используйте errors.As (или errors.Unwrap) вместо утверждения типа.

crypto/x509

Если имя в сертификате или проверяемое имя (с VerifyOptions.DNSName или VerifyHostname) недопустимы, они теперь будут сравниваться без учета регистра без дальнейшей обработки (без учета подстановочных знаков или удаления конечных точек). К недействительным именам относятся имена с любыми символами, кроме букв, цифр, дефисов и подчеркиваний, имена с пустыми метками и имена сертификатов с точками в конце.

Новая функция CreateRevocationList и тип RevocationList позволяют создавать списки отозванных сертификатов X.509 v2, соответствующие RFC 5280.

CreateCertificate теперь автоматически генерирует SubjectKeyId, если шаблон является центром сертификации и не указывает его явно.

CreateCertificate теперь возвращает ошибку, если в шаблоне указан MaxPathLen, но он не является центром сертификации.

В системах Unix, отличных от macOS, переменная среды SSL_CERT_DIR теперь может быть списком, разделенным двоеточиями.

В macOS двоичные файлы теперь всегда связаны с Security.framework для извлечения системных доверенных корней, независимо от того, доступно ли cgo. Полученное поведение должно быть более согласованным с верификатором ОС.

crypto/x509/pkix

Name.String теперь печатает нестандартные атрибуты из имен, если ExtraNames равно nil.

database/sql

Новый метод DB.SetConnMaxIdleTime позволяет удалить соединение из пула соединений после того, как оно какое-то время бездействовало, без учета общего срока жизни соединения. Поле DBStats.MaxIdleTimeClosed показывает общее количество соединений, закрытых из-за DB.SetConnMaxIdleTime.

Новый метод получения Row.Err позволяет проверять ошибки запроса без вызова Row.Scan.

database/sql/driver

Новый интерфейс Validator может быть реализован Conn, чтобы позволить драйверам сигнализировать, действительно ли соединение или его следует отменить.

debug/pe

Пакет теперь определяет константы IMAGE_FILE, IMAGE_SUBSYSTEM и IMAGE_DLLCHARACTERISTICS, используемые форматом файла PE.

encoding/asn1

Marshal теперь сортирует компоненты SET OF в соответствии с X.690 DER.

Unmarshal теперь отклоняет теги и идентификаторы объектов, которые минимально не закодированы в соответствии с X.690 DER.

encoding/json

Пакет теперь имеет внутреннее ограничение на максимальную глубину вложенности при декодировании. Это снижает вероятность того, что глубоко вложенный ввод может использовать большие объемы памяти стека или даже вызвать панику "goroutine stack exceeds limit".

flag

Когда пакет flag видит -h или -help, а эти флаги не определены, он теперь печатает сообщение об использовании. Если FlagSet был создан с ExitOnError, FlagSet.Parse будет завершен со статусом 2. В этом релизе статус выхода для -h или -help изменен на 0. В частности, это относится к обработке по умолчанию флагов коммандной строки.

fmt

Команды печати %#g и %#G теперь сохраняют конечные нули для значений с плавающей запятой.

go/format

Функции Source и Node теперь канонизируют префиксы и показатели числовых литералов как часть форматирования исходного кода Go. Это соответствует поведению команды gofmt, реализованной начиная с Go 1.13.

html/template

В пакете теперь используются escape-символы Unicode (\uNNNN) во всех контекстах JavaScript и JSON. Это исправляет ошибки экранирования в контекстах application/ld+json и application/json.

io/ioutil

TempDir и TempFile теперь отклоняют шаблоны, содержащие разделители путей. То есть такие вызовы, как ioutil.TempFile("/tmp", "../base*") больше не будут успешными. Это предотвращает непреднамеренный обход каталога.

math/big

Новый метод Int.FillBytes позволяет сериализовать в заранее выделенные байтовые срезы фиксированного размера.

math/cmplx

Функции в этом пакете были обновлены для соответствия стандарту C99 (приложение G, совместимое с IEC 60559 комплексная арифметика) в отношении обработки специальных аргументов, таких как бесконечность, NaN и ноль со знаком.

net

Если операция ввода-вывода превышает крайний срок, установленный методами Conn.SetDeadline, Conn.SetReadDeadline или Conn.SetWriteDeadline, она теперь будет возвращать ошибку, которая является os.ErrDeadlineExceeded или обертывает ее. Это может использоваться для надежного определения того, является ли ошибка следствием превышения крайнего срока. В более ранних выпусках рекомендовалось вызывать метод Timeout при ошибке, но операции ввода-вывода могут возвращать ошибки, для которых Timeout возвращает true, хотя крайний срок не был превышен.

Новый метод Resolver.LookupIP поддерживает поиск IP-адресов, который зависит от сети и принимает контекст.

net/http

Синтаксический анализ теперь является более строгой мерой защиты от атак контрабанды запросов (request smuggling attacks): пробелы, не относящиеся к ASCII, больше не обрезаются, как SP и HTAB, а поддержка "идентификационного" Transfer-Encoding была прекращена.

net/http/httputil

ReverseProxy теперь поддерживает запрет на изменение заголовка X-Forwarded-For, когда входящая запись карты Request.Header для этого поля равна nil.

Когда запрос протокола переключения (например, WebSocket), обрабатываемый ReverseProxy, отменяется, серверное соединение теперь закрывается правильно.

net/http/pprof

Все конечные точки профиля теперь поддерживают параметр "seconds". Если присутствует, конечная точка профилирует указанное количество секунд и сообщает о разнице. Значение параметра "seconds" в профиле процессора и конечных точек трассировки не изменилось.

net/url

Новое поле URL-адреса RawFragment и метод EscapedFragment предоставляют подробную информацию о точном кодировании конкретного фрагмента и контролируют его. Они аналогичны RawPath и EscapedPath.

Новый метод URL-адреса Redacted возвращает URL-адрес в строковой форме с заменой любого пароля на xxxxx.

os

Если операция ввода-вывода превышает крайний срок, установленный методами File.SetDeadline, File.SetReadDeadline или File.SetWriteDeadline, теперь она будет возвращать ошибку, которая является или обертывает os.ErrDeadlineExceeded. Это может использоваться для надежного определения того, является ли ошибка следствием превышения крайнего срока. В более ранних выпусках рекомендовалось вызывать метод Timeout при ошибке, но операции ввода-вывода могут возвращать ошибки, для которых Timeout возвращает true, хотя крайний срок не был превышен.

Пакеты os и net теперь автоматически повторяют системные вызовы, которые завершаются ошибкой с EINTR. Раньше это приводило к ложным сбоям, которые стали более распространенными в Go 1.14 с добавлением асинхронного прерывания. Теперь это делается прозрачно.

Тип os.File теперь поддерживает метод ReadFrom. Это позволяет использовать системный вызов copy_file_range в некоторых системах при использовании io.Copy для копирования данных из одного файла os.File в другой. Как следствие, io.CopyBuffer не всегда будет использовать указанный буфер при копировании в os.File. Если программа хочет принудительно использовать предоставленный буфер, это можно сделать, написав io.CopyBuffer(struct{ io.Writer }{dst}, src, buf).

plugin

Генерация DWARF теперь поддерживается (и включена по умолчанию) для -buildmode=plugin в macOS.

Сборка с -buildmode=plugin теперь поддерживается на freebsd/amd64.

reflect

Пакет reflect теперь запрещает доступ к методам всех неэкспортируемых полей, тогда как ранее он разрешал доступ к методам неэкспортированных встроенных полей. Код, основанный на предыдущем поведении, следует обновить, чтобы вместо этого получить доступ к соответствующему продвинутому методу включающей переменной.

regexp

Новый метод Regexp.SubexpIndex возвращает индекс первого подвыражения с заданным именем в регулярном выражении.

runtime

Некоторые функции, включая ReadMemStats и GoroutineProfile, больше не блокируются, если выполняется сборка мусора.

runtime/pprof

Профиль goroutine теперь включает метки профиля, связанные с каждой goroutine во время профилирования. Эта функция еще не реализована для профиля, о котором сообщается с debug=2.

strconv

FormatComplex и ParseComplex добавлены для работы с комплексными числами.

FormatComplex преобразует комплексное число в строку формы (a+bi), где a и b - действительная и мнимая части.

ParseComplex преобразует строку в комплексное число заданной точности. ParseComplex принимает комплексные числа в формате N+Ni.

sync

Новый метод Map.LoadAndDelete атомарно удаляет ключ и возвращает предыдущее значение, если оно есть.

Метод Map.Delete более эффективен.

syscall

В системах Unix функции, использующие SysProcAttr, теперь будут отклонять попытки установить оба поля Setctty и Foreground, поскольку они оба используют поле Ctty, но делают это несовместимыми способами. Ожидается, что некторые существующие программы устанавливают оба поля.

Для настройки поля Setctty теперь требуется, чтобы в поле Ctty был установлен номер дескриптора файла в дочернем процессе, как определено в поле ProcAttr.Files. Использование дочернего дескриптора всегда работало, но в некоторых случаях использование родительского файлового дескриптора также помогало. Некоторым программам, которые устанавливают Setctty, необходимо будет изменить значение Ctty, чтобы использовать номер дочернего дескриптора.

Теперь можно вызывать системные вызовы, возвращающие значения с плавающей запятой в windows/amd64.

testing

Тип testing.T теперь имеет метод Deadline, который сообщает время, когда тестовый двоичный файл превысит свой таймаут.

Функция TestMain больше не требуется для вызова os.Exit. Если функция TestMain вернется, тестовый двоичный файл вызовет os.Exit со значением, возвращаемым m.Run.

Новые методы T.TempDir и B.TempDir возвращают временные каталоги, которые автоматически очищаются в конце теста.

go test -v теперь группирует вывод по имени теста, а не печатает имя теста в каждой строке.

text/template

JSEscape теперь постоянно использует escape-символы Unicode (\u00XX), которые совместимы с JSON.

time

Новый метод Ticker.Reset поддерживает изменение длительности тикера.

При возврате ошибки ParseDuration теперь цитирует исходное значение.


Читайте также:


купить игрушку gopher

пятница, 14 августа 2020 г.

Релиз Go 1.15, runtime, компилятор, компоновщик

Среда времени выполнения (Runtime)

Если паника вызывается со значением, тип которого является производным от любого из: bool, complex64, complex128, float32, float64, int, int8, int16, int32, int64, string, uint, uint8, uint16, uint32, uint64, uintptr, тогда будет напечатано значение, а не только его адрес. Раньше это было верно только для значений именно этих типов.

В системе Unix, если команда kill или системный вызов kill используется для отправки сигнала SIGSEGV, SIGBUS или SIGFPE программе Go, и если сигнал не обрабатывается через os/signal.Notify, программа Go теперь будет надежно вылетать с трассировкой стека. В более ранних выпусках поведение было непредсказуемым.

Распределение небольших объектов теперь работает намного лучше при большом количестве ядер и имеет меньшую задержку в худшем случае.

Преобразование небольшого целочисленного значения в значение интерфейса больше не вызывает выделения.

Неблокирующие приемы по закрытым каналам теперь работают так же, как неблокирующие приемы по открытым каналам.

Компилятор

Правила безопасности package unsafe позволяют конвертировать unsafe.Pointer в uintptr при вызове определенных функций. Ранее в некоторых случаях компилятор допускал несколько связанных преобразований (например, syscall.Syscall(…, uintptr(uintptr(ptr)), …)). Теперь компилятору требуется ровно одно преобразование. Код, в котором использовалось несколько преобразований, следует обновить, чтобы он соответствовал правилам безопасности.

Go 1.15 уменьшает типичный двоичный размер примерно на 5% по сравнению с Go 1.14 за счет исключения определенных типов метаданных GC и более активного удаления метаданных неиспользуемых типов.

Цепочка инструментов теперь смягчает ошибку CPU Intel SKX102 на GOARCH=amd64, выравнивая функции по 32-байтовым границам и заполняя инструкции перехода. Хотя это заполнение увеличивает двоичный размер, это более чем компенсируется упомянутыми выше улучшениями двоичного размера.

Go 1.15 добавляет флаг -spectre как к компилятору, так и к ассемблеру, чтобы разрешить включение защиты от Spectre. В них почти никогда не должно быть необходимости, и они предоставляются в основном как механизм "глубокой защиты".

Теперь компилятор отклоняет компиляторные директивы //go: , которые не имеют значения для объявления, к которому они применяются, с ошибкой "неправильно размещенная директива компилятора". Такие неправильно примененные директивы ранее нарушались, но компилятор молча игнорировал их.

Ведение журнала оптимизации компилятора -json теперь сообщает о больших (>= 128 байт) копиях и включает объяснения решений анализа выхода.

Компновщик (Linker)

Этот выпуск включает в себя существенные улучшения компоновщика Go, которые сокращают использование ресурсов компоновщика (как время, так и память) и улучшают надежность кода/ремонтопригодность.

Для репрезентативного набора больших программ Go компоновка выполняется на 20% быстрее и требует в среднем на 30% меньше памяти для ОС на основе ELF (Linux, FreeBSD, NetBSD, OpenBSD, Dragonfly и Solaris), работающих на архитектурах amd64, с более скромными параметрами улучшения для других комбинаций архитектуры/ОС.

Ключевыми факторами повышения производительности компоновщика являются недавно переработанный формат объектного файла и переработка внутренних фаз для увеличения конкурентности (например, параллельное применение перемещений к символам). Объектные файлы в Go 1.15 немного больше, чем их эквиваленты в 1.14.

Эти изменения являются частью проекта с несколькими выпусками по модернизации компоновщика Go, а это означает, что в будущих выпусках ожидаются дополнительные улучшения компоновщика.

Компоновщик теперь по умолчанию использует режим внутренней компоновки для -buildmode=pie в linux/amd64 и linux/arm64, поэтому эти конфигурации больше не требуют компоновщика C.

Objdump

Инструмент objdump теперь поддерживает дизассемблирование в синтаксисе ассемблера GNU с флагом -gnu.


Читайте также:


четверг, 13 августа 2020 г.

Релиз Go 1.15, порты, инструменты

Выпуск Go, версия 1.15, выходит через шесть месяцев после Go 1.14. Большинство его изменений связано с реализацией цепочки инструментов, среды выполнения и библиотек. Как всегда, релиз поддерживает обещание Go 1 совместимости. Ожидается, что почти все программы Go будут продолжать компилироваться и работать как раньше.

Go 1.15 включает в себя существенные улучшения компоновщика, улучшает распределение для небольших объектов при большом количестве ядер и не поддерживает X.509 CommonName. GOPROXY теперь поддерживает пропуск прокси, возвращающих ошибки, и был добавлен новый встроенный пакет tzdata.

Изменений в языке нет.

Порты


Darwin

Как было объявлено в примечаниях к выпуску Go 1.14, для Go 1.15 требуется macOS 10.12 Sierra или новее; поддержка предыдущих версий прекращена.

Как было объявлено в примечаниях к выпуску Go 1.14, Go 1.15 отказывается от поддержки 32-битных двоичных файлов в macOS, iOS, iPadOS, watchOS и tvOS (порты darwin/386 и darwin/arm). Go продолжает поддерживать 64-битные порты darwin/amd64 и darwin/arm64.

Windows

Go теперь генерирует исполняемые файлы Windows ASLR, если указан флаг -buildmode=pie cmd/link. Команда Go по умолчанию использует -buildmode=pie в Windows.

Флаги -race и -msan теперь всегда включают -d=checkptr, который проверяет использование unsafe.Pointer. Раньше так было во всех ОС, кроме Windows.

Собранные на Go библиотеки DLL больше не вызывают завершение процесса при получении сигнала (например, Ctrl-C на терминале).

Android

При компоновке двоичных файлов для Android Go 1.15 явно выбирает компоновщик lld, доступный в последних версиях NDK. Компоновщик lld позволяет избежать сбоев на некоторых устройствах, и планируется, что он станет компоновщиком NDK по умолчанию в будущей версии NDK.

OpenBSD

Go 1.15 добавляет поддержку OpenBSD 6.7 на GOARCH=arm и GOARCH=arm64. Предыдущие версии Go уже поддерживали OpenBSD 6.7 на GOARCH=386 и GOARCH=amd64.

RISC-V

Достигнут прогресс в улучшении стабильности и производительности 64-разрядного порта RISC-V в Linux (GOOS=linux, GOARCH=riscv64). Он также теперь поддерживает асинхронное прерывание.

386

Go 1.15 - последний выпуск, который поддерживает оборудование с плавающей запятой только для x87 (GO386=387). В будущих выпусках потребуется как минимум поддержка SSE2 на 386, что повысит минимальное требование Go для GOARCH=386 до Intel Pentium 4 (выпущенного в 2000 году) или AMD Opteron/Athlon 64 (выпущенного в 2003 году).

Инструменты

Команда Go

Переменная среды GOPROXY теперь поддерживает пропуск прокси, возвращающих ошибки. URL-адреса прокси теперь можно разделять запятыми (,) или вертикальной чертой (|). Если за URL-адресом прокси-сервера стоит запятая, команда go будет пробовать только следующий прокси в списке после HTTP-ответа 404 или 410. Если после URL-адреса прокси-сервера следует вертикальная черта, команда go попробует следующий прокси в списке после любой ошибки. Обратите внимание, что значение GOPROXY по умолчанию остается https://proxy.golang.org,direct, которое не возвращается к direct в случае ошибок.

go test

Изменение флага -timeout теперь делает недействительными кешированные результаты теста. Кешированный результат для тестового запуска с длинным тайм-аутом больше не будет считаться пройденным, если go test повторно запускается с коротким.

Разбор флагов

Исправлены различные проблемы с синтаксическим анализом флагов в go test и go vet. Примечательно, что флаги, указанные в GOFLAGS, обрабатываются более последовательно, а флаг -outputdir теперь интерпретирует относительные пути относительно рабочего каталога команды go (а не рабочего каталога каждого отдельного теста).

Кеш модуля

Местоположение кэша модуля теперь можно задать с помощью переменной среды GOMODCACHE. Значение GOMODCACHE по умолчанию - GOPATH[0]/pkg/mod, расположение кэша модуля до этого изменения.

Теперь доступен обходной путь для ошибок Windows "Access is denied" в командах go, которые обращаются к кэшу модуля, вызванных одновременным сканированием файловой системы внешними программами. Обходной путь не включен по умолчанию, потому что его небезопасно использовать, когда версии Go ниже 1.14.2 и 1.13.10 работают одновременно с одним и тем же кешем модуля. Его можно включить, явно установив переменную среды GODEBUG=modcacheunzipinplace=1.

Vet


Новое предупреждение для string(x)

Инструмент vet теперь предупреждает о преобразованиях формы string(x), где x имеет целочисленный тип, отличный от rune или byte. Опыт работы с Go показал, что многие преобразования этой формы ошибочно предполагают, что string(x) оценивается как строковое представление целого числа x. Фактически он вычисляет строку, содержащую кодировку UTF-8 значения x. Например, string(9786) не оценивается как строка "9786"; а оценивается как строка "\xe2\x98\xba" или "☺️".

Код, который правильно использует string(x), можно переписать в string(rune(x)). Или, в некоторых случаях, правильным решением может быть вызов utf8.EncodeRune(buf, x) с подходящим байтовым срезом buf. Другой код, скорее всего, должен использовать strconv.Itoa или fmt.Sprint.

Эта новая vet проверка включена по умолчанию при использовании go test.

Рассматривается возможность запрета преобразования в будущем выпуске Go. То есть язык изменится, чтобы разрешить string(x) только для целого числа x, если тип x - rune или byte. Такое изменение языка не будет обратно совместимым. Эта vet проверка используется в качестве первого пробного шага к изменению языка.

Новое предупреждение о невозможности преобразования интерфейса

Инструмент vet теперь предупреждает об утверждениях типа от одного типа интерфейса к другому типу интерфейса, когда утверждение типа всегда терпит неудачу. Это произойдет, если оба типа интерфейса реализуют метод с тем же именем, но с другой сигнатурой типа.

Нет причин писать утверждение типа, которое всегда терпит неудачу, поэтому любой код, запускающий эту vet проверку, следует переписать.

Эта новая vet проверка включена по умолчанию при использовании go test.

Рассматривается возможность запрета утверждений о невозможных типах интерфейсов в будущих версиях Go. Такое изменение языка не будет обратно совместимым. Эта vet проверка используется в качестве первого пробного шага к изменению языка.


Читайте также: