go Advanced — подробное объяснение создания веб-сервиса + веб-сокета в GO.
go Advanced — подробное объяснение создания веб-сервиса + веб-сокета в GO.

1. GO реализует веб-сервисы

Go предоставляет набор очень простых стандартов для создания веб-серверов. Просто вызовите функцию ListenAndServe в пакете net/http и передайте сетевой адрес и процессор, ответственный за обработку. Библиотека net/http реализует интерфейсы клиента и сервера в полном наборе http-сервисов. На основании этого вы можете легко инициировать HTTP-запросы или предоставлять HTTP-сервисы внешнему миру.

Примечание 1. Если сетевой адрес пуст, для сетевого подключения по умолчанию используется порт 80 hhtp. Если параметр процессора равен нулю, используется мультиплексор по умолчанию DefaultServeMux.

После получения запроса пользователя мультиплексор определяет, какой процессор использовать для обработки запроса, на основе запрошенного URL-адреса, а затем перенаправляет соответствующий процессор для обработки запроса.

1. HTTP-процессор http.HandleFunc

HandleFunc

http.HandleFunc — это мультиплексор, который направляет запросы к указанному обработчику на основе URL-адреса. Обработчик используется для обработки запросов и предоставления ответов. Более строго говоря, он используется для чтения тела запроса, записи полей ответа (заголовков ответов), соответствующих запросу, в ResponseWriter и последующего возврата:

Что такое Хэндлер. Это интерфейс, определенный в net/http/server.go:

type Handler interface {     ServeHTTP(ResponseWriter, *Request) }

Другими словами, все те, кто реализует метод ServerHTTP, являются обработчиками. Обратите внимание на параметры метода ServerHTTP: интерфейс http.ResponesWriter и указатель запроса.

В комментариях Хэндлера дано несколько основных указаний:

Обработчик используется для ответа на HTTP-запрос. Метод интерфейса ServerHTTP следует использовать для записи заголовка ответа и данных, на которые необходимо ответить, в ResponseWriter, а затем возврата.

Интерфейс ResponseWriter

Интерфейс ResponseWriter используется для создания HTTP ответ и отправляет заголовок ответа и данные ответа клиенту через сетевую ссылку.

Язык кода:javascript
копировать
// A ResponseWriter interface is used by an HTTP handler to
// construct an HTTP response.
//
// A ResponseWriter may not be used after the Handler.ServeHTTP method
// has returned.
type ResponseWriter interface {
    Header() Header
    Write([]byte) (int, error)
    WriteHeader(statusCode int)
}

Этот интерфейс имеет 3 метода:

  • Метод Header() используется для создания заголовка ответа. Он возвращает объект Header, на который позже ответит WriterHeader(). Тип заголовка представляет собой структуру типа карты, имя поля — ключевое, а значение поля — значение:
Язык кода:javascript
копировать
type Header map[string][]string
  • Метод Write() используется для записи данных ответа в сетевое соединение.
  • Метод WriteHeader() отправляет заданный код состояния ответа и заголовок ответа вместе.

В Go есть функция HandleFunc(), что означает использование функции второго параметра в качестве обработчика для обработки запроса соответствующего URL-пути. Первый параметр HandleFunc относится к пути запроса, а второй параметр — это тип функции, указывающий, что необходимо обработать для этого запроса. Вместо обработки сложной логики она обрабатывается непосредственно DefaultServeMux, как показано в исходном коде:

Язык кода:javascript
копировать
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

Стандартная библиотека Golang net/http предоставляет интерфейсы, связанные с http-программированием, инкапсулируя сложные и тривиальные детали внутренних TCP-соединений и анализа сообщений. Пользователям нужно взаимодействовать только с двумя объектами: http.request и http.ResponseWriter.

Исходный код, эквивалентный адаптеру:

Язык кода:javascript
копировать
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

2. Создайте демо-версию процессора

Создайте метод процессора 1:

1.type HandlerFunc func(ResponseWriter,*Request)

  • Параметрами должны быть эти два ResponseWriter, *Request, процессор имеет обработчик интерфейса (метод реализации интерфейса для реализации интерфейса)
  • Создайте свой собственный процессор, реализовав интерфейс Handler.
  • Функция HandlerFunc поможет нам создать Handler и вызвать
Язык кода:javascript
копировать
package main
import (
   "fmt"
   "net/http"
)
     
//Создаем функцию-обработчик
func indexHandler(w http.ResponseWriter, r *http.Request) {
   fmt.Fprintf(w, "Hello world") //Ввод приветствия в файл wПисать world
}
     
func main() {
    //Находим процессор по URL Первый параметр естьURL
    http.HandleFunc("/", indexHandler)
    
    //Порт веб-прослушивания, прослушивание на локальном хосте: порт 9090, используйте DefaluteServeMux
    http.ListenAndServe(":9090", nil)
}

Запустите службу: запустите web.go

Запросить услугу:

Создайте метод процессора 1:Создайте свой собственныйHandler

Язык кода:javascript
копировать
package main
import (
        "fmt"
        "net/http"
)
     
//Объявляем структуру
type IndexHandler struct{}
     
//Привязываем метод ServeHTTP(....) интерфейса Handler к IndexHandler
func (this *IndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, «Я Мой Хэндлер»)
}
     
func main() {
     
    //Создаем экземпляр IndexHandler
    myHandler := IndexHandler{}
    //обрабатываем запрос
    http.Handle("/", &myHandler)
     
    http.ListenAndServe(":9090", nil)
}

2. Создайте мультиплексор

​ ​ GO предоставляет метод NewServerMux, позволяющий нам самостоятельно создать мультиплексор:

func NewServeMux() *ServeMux

Язык кода:javascript
копировать
package main   
import (
    "fmt"
    "net/http"
)
     
func sayHello(w http.ResponseWriter, r *http.Request) {
     fmt.Fprintln(w, "Hello golang")
}
     
func main() {
        myMux := http.NewServeMux()
        myMux.HandleFunc("/", sayHello)
        http.ListenAndServe(":9090", myMux)
}

3. Структура сервера

GO предоставляет структуру сервера. Мы можем создать экземпляр сервера для настройки некоторых конфигураций сервера.

Язык кода:javascript
копировать
type Server struct {
    Addr string // Определите адрес и порт, который прослушивает Служит. Если он пуст, по умолчанию он будет прослушивать порт 80.
    Handler Handler // Деловая сторона, чей запрос обрабатывается, по умолчанию http.DefaultServeMux
    TLSConfig *tls.Config // Дополнительная конфигурация TLS, обеспечивающая https-служить внешнему миру.
    ReadTimeout time.Duration // Таймаут чтения клиентских запросов, включая тело запроса на чтение
    ReadHeaderTimeout time.Duration // Таймаут чтения заголовков запроса, если пусто, используйте ReadTimeout, Если ни то, ни другое, тайм-аута нет.
    WriteTimeout time.Duration // Служить таймаут ответа
    IdleTimeout time.Duration // Тайм-аут простоя длинной ссылки
    MaxHeaderBytes int // Максимальный размер заголовка клиентского запроса, по умолчанию — 1 МБ.
    ConnState func(net.Conn, ConnState) // Укажите дополнительный метод обратного вызова при изменении статуса подключения клиента.
    ErrorLog *log.Logger // Используется при возникновении ошибок подключения, исключений обработчиков или файловой системы. По умолчанию используется интерфейс регистратора стандартной библиотеки.
    onShutdown []func() // Вызов метода срабатывает, когда Служить остановлено
} 

На основе приведенной выше структуры сервера стандартная библиотека Golang предоставляет следующие сервисные интерфейсы:

Язык кода:javascript
копировать
 func (srv *Server) Close() error // Немедленно закройте все активное прослушивание и все соединения, включая новые соединения, активные и простаивающие соединения.
func (srv *Server) ListenAndServe() error // Запустите Служить для мониторинга TCP-соединений и пересылки запросов обработчику.
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error // Поддержка httpsСлужить
func (srv *Server) Shutdown(ctx context.Context) error // Добейтесь корректного закрытия соединений. 

Создайте веб-сервис на основе приведенной выше структуры сервера:

Язык кода:javascript
копировать
package main
import (
        "fmt"
        "net/http"
)
     
type MyHandler2 struct{}
     
func (this *MyHandler2) ServeHTTP(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, «Маленький принц»)
}
     
func main() {
    myHandler := MyHandler2{}
    //Примечание: здесь нет функции HanlderFunc. Ее необходимо указать при определении сервера.
    server := http.Server{
       Addr:    ":9090",
       Handler: &myHandler,
    }
    server.ListenAndServe()
}

2. Базовый механизм веб-сервиса GO.

Происхождение веб-сервисов также происходит из одной точки, а именно из структуры Сервера.

1. Структура сервера

Язык кода:javascript
копировать
 srv := http.Server{
    Addr: ":9090",
Здесь инициализируется служба сервера. Помимо отображения указанного порта прослушивания, существует также важный параметр обработчика по умолчанию, а именно http.DefaultServeMux, который обеспечивает функцию разрешения маршрута веб-службы. Прямо сейчас  

Здесь инициализируется служба сервера. Помимо отображения указанного порта прослушивания, существует также важный параметр обработчика по умолчанию, а именно http.DefaultServeMux, который обеспечивает функцию разрешения маршрута веб-службы. Прямо сейчас

Язык кода:javascript
копировать
  http.HandleFunc("/", helloWorldHandler)  

Приведенный выше код фактически эквивалентен следующему:

Язык кода:javascript
копировать
 handler := http.DefaultServeMux
handler.HandleFunc("/", helloWorldHandler)
srv := http.Server{
    Addr: ":9090",
    Handler: handler,
}  

Мультиплексор http поддерживает таблицу сопоставления для разрешения маршрутов. При запуске службы все маршруты запросов будут анализироваться в этой таблице сопоставления. Ее структура:

Язык кода:javascript
копировать
 type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry
    es    []muxEntry // slice of entries sorted from longest to shortest.
    hosts bool       // whether any patterns contain hostnames
}

type muxEntry struct {
    h       Handler
    pattern string
}  

Путь маршрута и соответствующий обработчик метода обработки хранятся в muxEntry. На основе этого интерфейса Mux также можно реализовать более сложные протоколы маршрутизации.

2. Обработка запросов

Язык кода:javascript
копировать
 er := srv.ListenAndServe()  

С помощью приведенного выше простого кода реализуется мониторинг и обслуживание сервиса. Так как же он это делает? С сомнениями я еще раз вошел в море кодов, чтобы найти код.

Язык кода:javascript
копировать
 func (srv *Server) ListenAndServe() error {
    if srv.shuttingDown() {
        return ErrServerClosed
    }
    addr := srv.Addr
    if addr == "" {
        addr = ":http"
    }
    ln, err := net.Listen("tcp", addr)
    if err != nil {
        return err
    }
    return srv.Serve(ln)
}

func (srv *Server) Serve(l net.Listener) error {
    if fn := testHookServerServe; fn != nil {
        fn(srv, l) // call hook with unwrapped listener
    }

    origListener := l
    l = &onceCloseListener{Listener: l}
    defer l.Close()

    if err := srv.setupHTTP2_Serve(); err != nil {
        return err
    }

    if !srv.trackListener(&l, true) {
        return ErrServerClosed
    }
    defer srv.trackListener(&l, false)

    baseCtx := context.Background()
    if srv.BaseContext != nil {
        baseCtx = srv.BaseContext(origListener)
        if baseCtx == nil {
            panic("BaseContext returned a nil context")
        }
    }

    var tempDelay time.Duration // how long to sleep on accept failure

    ctx := context.WithValue(baseCtx, ServerContextKey, srv)
    for {
        rw, err := l.Accept()
        if err != nil {
            select {
            case <-srv.getDoneChan():
                return ErrServerClosed
            default:
            }
            if ne, ok := err.(net.Error); ok && ne.Temporary() {
                if tempDelay == 0 {
                    tempDelay = 5 * time.Millisecond
                } else {
                    tempDelay *= 2
                }
                if max := 1 * time.Second; tempDelay > max {
                    tempDelay = max
                }
                srv.logf("http: Accept error: %v; retrying in %v", err, tempDelay)
                time.Sleep(tempDelay)
                continue
            }
            return err
        }
        connCtx := ctx
        if cc := srv.ConnContext; cc != nil {
            connCtx = cc(connCtx, rw)
            if connCtx == nil {
                panic("ConnContext returned nil")
            }
        }
        tempDelay = 0
        c := srv.newConn(rw)
        c.setState(c.rwc, StateNew) // before Serve can return
        go c.serve(connCtx)
    }
}  

Видно, что Golang получает веб-страницу по протоколу TCP, а затем вызывает метод Serve для обработки запроса на соединение. Метод Serve запускает горутину для асинхронной обработки, что также является основой высокого параллелизма.

В методе обслуживания клиентский запрос принимается и обрабатывается в бесконечном цикле (for). Основная логика следующая:

Язык кода:javascript
копировать
 if tlsConn, ok := c.rwc.(*tls.Conn); ok {
        if d := c.server.ReadTimeout; d != 0 {
            c.rwc.SetReadDeadline(time.Now().Add(d))
        }
        if d := c.server.WriteTimeout; d != 0 {
            c.rwc.SetWriteDeadline(time.Now().Add(d))
        }
        if err := tlsConn.Handshake(); err != nil {
            // If the handshake failed due to the client not speaking
            // TLS, assume they're speaking plaintext HTTP and write a
            // 400 response on the TLS conn's underlying net.Conn.
            if re, ok := err.(tls.RecordHeaderError); ok && re.Conn != nil && tlsRecordHeaderLooksLikeHTTP(re.RecordHeader) {
                io.WriteString(re.Conn, "HTTP/1.0 400 Bad Request\r\n\r\nClient sent an HTTP request to an HTTPS server.\n")
                re.Conn.Close()
                return
            }
            c.server.logf("http: TLS handshake error from %s: %v", c.rwc.RemoteAddr(), err)
            return
        }
        c.tlsState = new(tls.ConnectionState)
        *c.tlsState = tlsConn.ConnectionState()
        if proto := c.tlsState.NegotiatedProtocol; validNextProto(proto) {
            if fn := c.server.TLSNextProto[proto]; fn != nil {
                h := initALPNRequest{ctx, tlsConn, serverHandler{c.server}}
                fn(c.server, tlsConn, h)
            }
            return
        }
    }
    
    ...
    serverHandler{c.server}.ServeHTTP(w, w.req)  

Среди них реализация ServeHTTP:

Язык кода:javascript
копировать
 func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    handler := sh.srv.Handler
    if handler == nil {
        handler = DefaultServeMux
    }
    if req.RequestURI == "*" && req.Method == "OPTIONS" {
        handler = globalOptionsHandler{}
    }
    handler.ServeHTTP(rw, req)
}  

Здесь мы наконец находим метод-обработчик для обработки маршрутизации, который мы определили.

Весь процесс показан на рисунке:

Просматривая приведенный выше исходный код, мы можем в основном понять общий процесс обработки веб-запроса в golang.

3、Request

Запрос — это инкапсулированный клиентский запрос, включающий всю информацию, такую ​​как URL, метод, заголовок и т. д., а также некоторые удобные методы:

Любая информация, которую обработчик должен знать о запросе, должна быть получена из этого объекта. Как правило, этот объект не будет изменен напрямую.

Язык кода:javascript
копировать
type Request struct {
    // Method specifies the HTTP method (GET, POST, PUT, etc.).For client requests an empty string means GET.
    Method string

    // URL specifies either the URI being requested (for server requests) or the URL to access (for client requests).
    URL *url.URL

    // The protocol version for incoming requests.
    // Client requests always use HTTP/1.1.
    Proto      string // "HTTP/1.1"
    ProtoMajor int    // 1
    ProtoMinor int    // 1

    // A header maps request lines to their values.
    // If the header says
    //
    //    accept-encoding: gzip, deflate
    //    Accept-Language: en-us
    //    Connection: keep-alive
    //
    // then
    //
    //    Header = map[string][]string{
    //        "Accept-Encoding": {"gzip, deflate"},
    //        "Accept-Language": {"en-us"},
    //        "Connection": {"keep-alive"},
    //    }
    Header Header

    // Body is the request's body.
    Body io.ReadCloser
    ContentLength int64
    TransferEncoding []string
    Close bool
    Host string
    Form url.Values
    PostForm url.Values
    MultipartForm *multipart.Form
    ...
    RemoteAddr string
    ...
}

4、ResponseWriter

ResponseWriter — это интерфейс, определяющий три метода:

Header(): возвращает объект Header. Вы можете установить заголовок с помощью метода Set(). Обратите внимание, что окончательная возвращаемая информация заголовка может не совпадать с той, которую вы написали, поскольку последующая обработка также может изменить значение объекта. заголовок (например, Set Content-Length, Content-type и другие операции) Write(): напишите основную часть ответа, например, здесь будет размещен контент в формате html или json. WriteHeader(): установка кода состояния. Если эта функция не вызывается, значением по умолчанию является http.StatusOK, то есть код состояния 211.

Язык кода:javascript
копировать
// A ResponseWriter interface is used by an HTTP handler to
// construct an HTTP response.
type ResponseWriter interface {
    Header() Header
    Write([]byte) (int, error)
    WriteHeader(int)
}

3. веб-сокет

1. Введение в gorilla/websocket

websocketЗависит отhttpобновление Приходить,Сначала отправьте HTTP-запрос с заголовком запроса на обновление.,Поэтому нам нужно разобраться сHttpПерехватить запрос при запросе и определить, является ли онwebsocketобновлениепросить,Если да, то позвонитеgorilla/websocketОбработка соответствующей функции библиотекиобновлениепросить。

Веб-сокету, реализованному официальной стандартной библиотекой Golang, несколько недостает функциональности. Представленная на этот раз библиотека gorilla/websocket представляет собой быструю, высококачественную и широко используемую библиотеку веб-сокетов, созданную Gorilla, которая компенсирует функциональные недостатки стандартной библиотеки. . не хватает. Кроме того, набор инструментов Gorilla Web содержит несколько практических библиотек инструментов, связанных с HTTP-приложениями. Если вам интересно, вы можете перейти на официальный сайт https://www.gorillatoolkit.org, чтобы получить его.

Библиотека gorilla/websocket представляет собой реализацию протокола websocket, определенного в RFC 6455. С точки зрения отправки и получения данных она предоставляет два типа API детального чтения и записи сообщений: сообщения данных и управляющие сообщения с точки зрения производительности; связанные параметры конфигурации для буферов и сжатия с точки зрения безопасности, вы можете использовать CheckOrigin, чтобы контролировать, поддерживается ли междоменная поддержка.

2、gorilla/websocketРуководство пользователя

Установить:
Язык кода:javascript
копировать
go get github.com/gorilla/websocket
демонстрация кода сервера
Язык кода:javascript
копировать
package main

import (
	"fmt"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  4196,
	WriteBufferSize: 1124,
	CheckOrigin: func(r *http.Request) bool {

		//if r.Method != "GET" {
		//	fmt.Println("method is not GET")
		//	return false
		//}
		//if r.URL.Path != "/ws" {
		//	fmt.Println("path error")
		//	return false
		//}
		return true
	},
}

// ServerHTTP для обновления протоколов
func ServerHTTP(w http.ResponseWriter, r *http.Request) {
	// Обновите протокол после получения http-запроса.
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println("Error during connection upgrade:", err)
		return
	}
	defer conn.Close()

	for {
		// Сторона Служить читает запрос клиента
		messageType, message, err := conn.ReadMessage()
		if err != nil {
			log.Println("Error during message reading:", err)
			break
		}
		log.Printf("Received:%s", message)

		// Включение и выключение мониторинга соединения
		conn.SetCloseHandler(func(code int, text string) error {
			fmt.Println(code, text) // код и текст будут напечатаны при отключении
			return nil
		})

		//Конец Служить возвращает запрос клиенту
		err = conn.WriteMessage(messageType, message)
		if err != nil {
			log.Println("Error during message writing:", err)
			return
		}

	}
}

func home(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Index Page")
}

func main() {
	http.HandleFunc("/socket", ServerHTTP)
	http.HandleFunc("/", home)
	log.Fatal(http.ListenAndServe("localhost:8181", nil))
}

3. Конкретный процесс использования gorilla/websocket:

3.1. Сначала создайте экземпляр Upgrader для запросов на обновление.

UpgraderОтправлено сUpgradeпроситьголоваHttpпросить,Пучок http Запрос на переход на длинное соединение WebSocket,Структура следующая:

Язык кода:javascript
копировать
type Upgrader struct {
    // обновление websocket Тайм-аут завершения рукопожатия
    HandshakeTimeout time.Duration

    // io Размер кэша операции будет выделен автоматически, если не указан.
    ReadBufferSize, WriteBufferSize int

    // Писать пул кэша для операций с данными, если значение не задано, напишите buffers Будет выделено жизненному циклу ссылки.
    WriteBufferPool BufferPool

    //Укажите по порядку протокол, поддерживаемый Служить. Если значение существует, Служить будет соответствовать протоколу клиента, начиная с первого.
    Subprotocols []string

    // http функция реагирования на ошибку, если не установлена Error Затем он будет генерировать http.Error ответ об ошибке.
    Error func(w http.ResponseWriter, r *http.Request, status int, reason error)

    // CheckOrigin вернет true, если заголовок Origin запроса приемлем. Если CheckOrigin равен нулю, используется безопасное значение по умолчанию: если заголовок запроса Origin присутствует и хост-источник не равен заголовку хоста запроса, возвращается false.
    // Функция проверки запросов для унифицированной проверки ссылок для предотвращения подделки межсайтовых запросов. Если флажок не установлен, установите функцию с возвращаемым значением true.
    CheckOrigin func(r *http.Request) bool

    // EnableCompression Указывает, должен ли сервер Служить пытаться согласовать сжатие каждой почты (RFC 7692)。 Установка для этого значения значения true не гарантирует поддержку сжатия. В настоящее время поддерживается только режим «бесконтекстного поглощения».
    EnableCompression bool
}

Пример создания экземпляра Upgrader для запроса на обновление:

Язык кода:javascript
копировать
var upgrader = websocket.Upgrader{
    ReadBufferSize:  1124, //Указываем размер кэша чтения
    WriteBufferSize: 1124, //Указываем размер кэша Писать
    CheckOrigin:     checkOrigin,
}
// Определить источник запроса
func checkOrigin(r *http.Request) bool {
    if r.Method != "GET" {
        fmt.Println("method is not GET")
        return false
    }
    if r.URL.Path != "/ws" {
        fmt.Println("path error")
        return false
    }
    return true
}

вCheckOringinэто функция,Эта функция используется дляперехватыватьиливыпускать Междоменный доменпросить。Возвращаемое значение функцииboolтип,Прямо сейчасtrueвыпускать,falseперехватывать。еслипросить不是Междоменный доменпросить Никакое значение не может быть присвоено。

3.2. Обновите протокол для получения соединения.
Язык кода:javascript
копировать
func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header) (*Conn, error)
  • Функция обновляет http до протокола WebSocket, возвращает указатель Conn и использует Conn для чтения и записи данных для связи с клиентом.
  • responseHeader включается в ответ на запрос обновления клиента.
  • Используйте responseHeader, чтобы указать файл cookie (Set-Cookie) и подпротокол, согласованный приложением (Sec-WebSocket-Protocol).
  • Если обновление не удалось, обновление ответит клиенту ответом об ошибке HTTP.

Перейдите на соединение через веб-сокет и получите экземпляр conn. Все последующие операции отправки и получения имеют соединение, а его тип — websocket.Conn.

3.3、Отправить сообщение клиентуWriteMessage

первый Отправьте сообщение клиенту, используяWriteMessage(messageType int, data []byte),Параметр 1 — тип сообщения, параметр 2 — содержание сообщения:

Язык кода:javascript
копировать
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    //суждениепросить Этоwebsocketобновлениепросить。
    if websocket.IsWebSocketUpgrade(r) {
        conn, err := upgrader.Upgrade(w, r, w.Header())
        conn.WriteMessage(websocket.TextMessage, []byte("hgs"))
    } else {
        //Обработка обычных запросов
        c := newContext(w, r)
        e.router.handle(c)
    }
}

Или используйте метод func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) для получения средства записи, а затем вызовите func (w *messageWriter) Write(p []byte) (int, error) для записи данные.

 3.4、Принимать сообщения клиентовReadMessage()

Принимайте сообщения клиентов, используяReadMessage()Эта операция заблокирует поток, поэтому рекомендуется запускать ее на других сопрограммах.。Эта функция имеет три возвращаемых значения:,получать сообщениятип、Получить содержимое сообщения, произошла ошибка. Разумеется, ошибка при обычном выполнении есть. ноль. После закрытия соединения тип возвращаемого значения -1 можно использовать для завершения операции чтения. Пример:

Язык кода:javascript
копировать
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    //суждениепросить Этоwebsocketобновлениепросить。
    if websocket.IsWebSocketUpgrade(r) {
        conn, err := upgrader.Upgrade(w, r, w.Header())
        conn.WriteMessage(websocket.TextMessage, []byte("wxm.alming"))
        go func() {
            for {
                t, c, _ := conn.ReadMessage()
                fmt.Println(t, string(c))
                if t == -1 {
                    return
                }
            }
        }()
    } else {
        //Обработка обычных запросов
        c := newContext(w, r)
        e.router.handle(c)
    }
}
3.5 Отключите мониторинг подключения в настройках подключения.

При этом вы можете отключить мониторинг подключения в настройках подключения.,ФункцияSetCloseHandler(h func(code int, text string) error)Функция получает Функцияпараметр,Существует реализация по умолчанию, когда параметр равен нулю.,Его исходный код:

Язык кода:javascript
копировать
func (c *Conn) SetCloseHandler(h func(code int, text string) error) {
    if h == nil {
        h = func(code int, text string) error {
            message := FormatCloseMessage(code, "")
            c.WriteControl(CloseMessage, message, time.Now().Add(writeWait))
            return nil
        }
    }
    c.handleClose = h
}

Вы можете видеть, что параметрами функции являются типы int и string, которые точно такие же, как и во внешнем интерфейсе close(long строка) соответствует внешнему вызову close(long string)После закрытия соединения два параметра будут отправлены на серверную часть и, в конечном итоге,func(code int, text string) errorиспользовал。

Язык кода:javascript
копировать
//Http-вход
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    //суждениепросить Этоwebsocketобновлениепросить。
    if websocket.IsWebSocketUpgrade(r) {
        // получать http проситьназадобновлениепротокол
        conn, err := upgrader.Upgrade(w, r, w.Header())
        conn.SetCloseHandler(func(code int, text string) error {
            fmt.Println(code, text)
            return nil
        })
        // Отправьте сообщение клиенту, используя WriteMessage(messageType int, data []байт), параметр 1 — тип сообщения, параметр 2 — содержимое сообщения
        conn.WriteMessage(websocket.TextMessage, []byte("обновлениеуспех"))
        // Принимайте сообщения клиентов, используя ReadMessage(), эта операция блокирует поток, поэтому рекомендуется запускать ее на других сопрограммах.
        //Возвращаемое значение (тип полученного сообщения, содержимое полученного сообщения, произошла ошибка) Конечно, ошибка при обычном выполнении ноль. После закрытия соединения тип возвращаемого значения -1 можно использовать для завершения операции чтения.
        go func() {
            for {
                t, c, _ := conn.ReadMessage()
                fmt.Println(t, string(c))
                if t == -1 {
                    return
                }
            }
        }()
    } else {
        //Обработка обычных запросов
        c := newContext(w, r)
        e.router.handle(c)
    }
}

Код и текст будут напечатаны при отключении

Уведомление:Чтобы обработка отключения вступила в силу, должно бытьReadMessage()В противном случае операция обработки отключения не будет запущена.。

4. Фреймворк веб-разработки на языке Go включает в себя

Когда вы видите так много сред разработки, вы, возможно, какое-то время не знаете, какой выбрать. Xiaomu в основном рекомендует три платформы: Beego, Gin и Iris~

(1) Биго

Особенности фреймворка:

  • упрощать

Beego — это фреймворк в стиле RESTful с моделью MVC. Он поддерживает горячую компиляцию кода, автоматическое тестирование, автоматическую упаковку и развертывание, а также быструю разработку проектов, что делает разработку быстрее и проще.

  • Разумный

Beego не только поддерживает интеллектуальную маршрутизацию, но также решает проблему, связанную с тем, что платформа Mux не поддерживает параметры маршрутизации. Кроме того, Beego также может выполнять интеллектуальный мониторинг количества запросов в секунду, потребления памяти, использования ЦП и состояния работы горутины, что позволяет разработчикам, а также персоналу по эксплуатации и техническому обслуживанию легче отслеживать текущий статус онлайн-проектов.

  • Модульный

Beego имеет встроенные восемь модулей: сеанс, работа с кэшем, ведение журнала, анализ конфигурации, мониторинг производительности, работа с контекстом, ORM и моделирование запросов, что делает разработку более удобной.

  • высокая производительность

Поскольку Beego использует встроенный HTTP-пакет языка Go для обработки сетевых запросов, Beego может полностью использовать функции поддержки параллелизма языка Go. В настоящее время существует множество продуктов с высоким уровнем параллелизма, разработанных с использованием платформы Beego.

Причины рекомендации:

Beego — это простая и удобная в использовании среда разработки приложений Go корпоративного уровня, разработанная экспертом по разработке языка Go «Asta Xie». У нее есть официальный веб-сайт и учебные пособия на китайском языке. В отличие от других языков платформы, Beego предоставляет не только графические руководства. Также предоставляются видеоуроки, что очень удобно для отечественных разработчиков.

(2) Джин

Особенности фреймворка:

  • высокая производительность

Gin разработан на основе идей Martini, первой среды веб-разработки для языка Go. Он использует модуль httprouter для увеличения скорости почти в 40 раз.

  • Поддержка промежуточного программного обеспечения

Фреймворк Gin имеет множество встроенных промежуточных программ, таких как Logger, Gzip, Authorization и т. д. В то же время, если вы хотите расширить промежуточное программное обеспечение, Gin также очень удобен.

  • Встроенный валидатор данных

Gin имеет встроенные средства проверки данных, а также поддерживает определяемые пользователем средства проверки данных.

  • Управление ошибками

Gin может собирать информацию об ошибках во время работы программы и фиксировать сбои программы, вызванные паникой, тем самым гарантируя, что наши веб-приложения всегда работают нормально.

  • Поддержка нескольких форматов данных

Gin поддерживает стандартный формат данных формы, формат данных JSON, формат данных XML и формат данных YAML.

  • Поддержка привязки модели

По умолчанию Gin поддерживает два метода привязки модели для привязки данных запроса к типам, а именно метод Must Bind и метод Must Bind.

Причины рекомендации:

Веб-фреймворк Http, полностью написанный на языке Go, обеспечивающий более быструю и высокопроизводительную среду веб-разработки на языке Go.

(3) Ирис

Особенности фреймворка:

  • высокая производительность

По этому поводу есть поговорка: Iris — самый быстрый фреймворк для веб-разработки на Go. Что касается конкретной скорости, мы можем зайти на официальный сайт, чтобы увидеть результаты тестов, или самостоятельно загрузить код фреймворка и запустить тест производительности, чтобы увидеть результаты.

  • Простой API

Iris называется версией Javascript/Node.js на языке Go. Он имеет очень простой API, облегчающий начало работы разработчиков.

  • Поддержка промежуточного программного обеспечения

Iris имеет множество встроенных промежуточных программ, а также поддерживает пользовательские промежуточные программы, такие как ведение журналов, управление разрешениями, междоменные запросы и т. д.

  • Пользовательские ошибки HTTP

Платформа Iris может настраивать соответствующие функции обработки для любого HTTP-запроса.

  • Поддержка нескольких форматов данных

Iris поддерживает несколько форматов данных, таких как уценка, xml, Json и Jsonp, для рендеринга представления.

  • Горячая загрузка

При разработке с использованием платформы Iris новый контент будет автоматически компилироваться и загружаться при изменении исходного кода.

Причины рекомендации:

Если вы выбираете среду веб-разработки на языке Go с хорошей производительностью, легкостью и простотой в использовании, Iris — хороший выбор.

В конце концов, вы можете протестировать и узнать, какой фреймворк вы выберете.

Фреймворки — это инструменты для нашего развития. Только когда эти инструменты удобны, мы можем по-настоящему повысить эффективность нашей разработки.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose