Используйте go-module в качестве менеджера пакетов для создания веб-сервера go

Go
Используйте go-module в качестве менеджера пакетов для создания веб-сервера go

В этом блоге в основном рассказывается, как начать с нуля, использовать модуль Go для управления зависимостями и шаг за шагом создавать веб-сервер Go на основе Gin. И используйте Endless для плавного перезапуска сервера, и используйте Swagger для автоматического создания документации API.

Исходный код находится здесь:Исходный код проекта

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

среда сборки

Все приведенные ниже шаги основаны на MacOS.

установить идти

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

brew install go

После запуска команды введите в командной строкеgo. Если вы видите следующий вывод в командной строке, установка прошла успешно.

Go is a tool for managing Go source code.
Usage:
	go <command> [arguments]
The commands are:
...
...

Следует отметить, что версия go должна быть в1.11выше, иначе модуль go не может быть использован. Ниже моя версия go.

go version
# go version go1.12.5 darwin/amd64

IDE

Рекомендуемое использованиеGoLand

настроить GOPATH

Откройте GoLand, найдите Global GOPATH в настройках GoLand, установите для него значение$HOME/go.$HOMEКаталог — это пользовательский каталог вашего компьютера, если такого каталога нетgoЕсли нет необходимости создавать новый каталог, когда мы инициализируем модуль в следующей операции, он автоматически создаст новый каталог go в пользовательском каталоге.

Включить модуль GO

Опять же, найдите Go Modules (vgo) в настройках GoLand. Установите флажок перед интеграцией модулей Go (vgo), чтобы включить Go Moudle.

Создайте структуру проекта

новый каталог

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

инициализировать модуль go

go mod init $MODULE_NAME

В корневом каталоге только что созданного проекта используйте приведенную выше команду для инициализации модуля go. Эта команда создаст новый файл go.mod в корневом каталоге проекта.

Если ваш проект клонирован с github,$MODULE_NAMEЭтот параметр не нужен. по умолчанию это будетgithub.com/$GITHUB_USER_NAME/$PROJECT_NAME.

Например, этот проектgithub.com/detectiveHLH/go-backend-starter; Если это новый проект локально, необходимо добавить последний параметр. В противном случае будет обнаружена следующая ошибка.

go: cannot determine module path for source directory /Users/hulunhao/Projects/go/test/src (outside GOPATH, no import comments)

после инициализацииgo.modСодержимое файла следующее.

module github.com/detectiveHLH/go-backend-starter

go 1.12

Новый main.go

Создайте новый main.go в корневом каталоге проекта. код показывает, как показано ниже.

package main

import (
	"fmt"
)

func main() {
	fmt.Println("This works")
}

запустить main.go

использовать в корневом каталогеgo run main.go, если вы видите вывод командной строкиThis worksЭто означает, что основная структура была построена. Далее мы начинаем внедрять Gin во фреймворк.

Представьте Джин

GinЭто HTTP-веб-фреймворк, реализованный на Go, и мы используем Gin в качестве базовой фреймворка для начала.

Установить Джин

Установить напрямую через команду go get

go get github.com/gin-gonic/gin

После успешной установки мы видим, что содержимое в файле go.mod изменилось.

Более того, мы не видели только что установленных зависимостей под установленным GOPATH. На самом деле зависимости устанавливаются в $GOPATH/pkg/mod.

module github.com/detectiveHLH/go-backend-starter

go 1.12

require github.com/gin-gonic/gin v1.4.0 // indirect

При этом также создается файл go.sum. Содержание следующее.

github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

Любой, кто использовал Node, знает, что после установки зависимостей генерируется файл package-lock.json для блокировки версии зависимостей. Чтобы предотвратить установку новой версии при последующей переустановке зависимостей, но она несовместима с существующим кодом, что приведет к некоторым ненужным ошибкам.

Но этот файл go.sum этого не делает. Мы видим, что в go.mod записана только одна зависимость Gin, а в go.sum их намного больше. Это связано с тем, что в go.mod записывается только верхний уровень, то есть зависимости, которые мы устанавливаем непосредственно с помощью командной строки. Но имейте в виду, что пакет с открытым исходным кодом обычно зависит от многих других зависимостей.

И go.sum — это файл, который записывает конкретную версию всех высокоуровневых и косвенно зависимых пакетов и генерирует конкретное хэш-значение для каждой зависимой версии, так что, когда проект включается в новой среде, он может зависеть от проект.100% реставрация. go.sum также хранит некоторую информацию о версиях, использовавшихся в прошлом.

В модуле go нет необходимости в каталоге поставщика для обеспечения воспроизводимых сборок, но нужен файл go.mod для точного управления версиями каждой зависимости в проекте.

Если в предыдущем проекте использовался вендор, переписывать его с помощью go.mod нецелесообразно. мы можем использоватьgo mod vendorКоманда копирует все зависимости предыдущего проекта в каталог vendor.Для обеспечения совместимости зависимости в каталоге vendor отличаются от go.mod. Каталог после копирования не содержит номер версии.

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

Давайте взглянем на команды, связанные с go mod.

  • init инициализирует модуль go
  • загрузить Загрузите зависимости из go.mod в каталог локального кеша ($GOPATH/pkg/mod)
  • edit Отредактируйте go.mod, вручную обновите и получите зависимости через командную строку
  • поставщик копирует зависимости проекта поставщику
  • tidy устанавливает отсутствующие зависимости и отбрасывает бесполезные зависимости
  • graph печатает график зависимости модуля
  • проверить убедиться, что зависимости верны

Стоит упомянуть еще одну команду,go list -m allСписок сборки для текущего проекта может быть указан.

Изменить main.go

Код для изменения main.go выглядит следующим образом.

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
)

func main() {
	fmt.Println("This works.")
	r := gin.Default()
	r.GET("/hello", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"success": true,
			"code": 200,
			"message": "This works",
			"data": nil,
		})
	})
	r.Run()
}

Приведенный выше код вводит маршрутизацию.Те, кто знаком с Node, должны заметить, что это очень похоже на использование koa-router.

запустить сервер

Выполните шаги, описанные выше, чтобы запустить main.go для запуска main.go. Вы можете увидеть следующий вывод в консоли.

This works.
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /hello                    --> main.main.func1 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080

На данный момент сервер запущен на порту 8080. Затем посетите http://localhost:8080/hello в браузере, вы увидите нормальное возвращение сервера. При этом серверная сторона также распечатает соответствующий лог.

[GIN] 2019/06/08 - 17:41:34 | 200 |     214.213µs |             ::1 | GET      /hello

построить маршрут

Создайте новый модуль маршрутизации

Создайте новый каталог маршрутизатора в корневом каталоге. Под маршрутизатором создайте новый файл router.go со следующим кодом.

package router

import "github.com/gin-gonic/gin"

func InitRouter() *gin.Engine {
	router := gin.New()
	apiVersionOne := router.Group("/api/v1/")
	apiVersionOne.GET("hello", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"success": true,
			"code": 200,
			"message": "This works",
			"data": nil,
		})
	})
	return router
}

В этот файл экспортируется функция InitRouter, которая возвращает тип gin.Engine. Функция также определяет запрос GET, направляемый в /api/v1/hello.

Внедрить маршрутизацию в основную функцию

Измените код main.go на следующий.

package main

import (
	"fmt"
	"github.com/detectiveHLH/go-backend-starter/router"
)

func main() {
	r := router.InitRouter()
	r.Run()
}

Затем запустите main.go, после запуска посетитеhttp://localhost:8080/api/v1/hello, вы можете видеть, что результат доступа к маршруту /hello такой же, как и раньше.

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

Внедрить JWT-аутентификацию

Установите зависимости jwt-go с помощью команды go get.

go get github.com/dgrijalva/jwt-go

Создайте новый файл аутентификации jwt

Создайте новый каталог промежуточного ПО/jwt в корневом каталоге и создайте новый файл jwt.go в каталоге jwt.Код выглядит следующим образом.

package jwt

import (
  "github.com/detectiveHLH/go-backend-starter/consts"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

func Jwt() gin.HandlerFunc {
	return func(c *gin.Context) {
		var code int
		var data interface{}

		code = consts.SUCCESS
		token := c.Query("token")
		if token == "" {
			code = consts.INVALID_PARAMS
		} else {
			claims, err := util.ParseToken(token)
			if err != nil {
				code = consts.ERROR_AUTH_CHECK_TOKEN_FAIL
			} else if time.Now().Unix() > claims.ExpiresAt {
				code = consts.ERROR_AUTH_CHECK_TOKEN_TIMEOUT
			}
		}

		if code != consts.SUCCESS {
			c.JSON(http.StatusUnauthorized, gin.H{
				"code": code,
				"msg":  consts.GetMsg(code),
				"data": data,
			})

			c.Abort()
			return
		}

		c.Next()
	}
}

Ввести константы

На этом этапе в коде будут ошибки, потому что мы не объявили пакет consts, а переменные SUCCESS, INVALID_PARAMS и ERROR_AUTH_CHECK_TOKEN_FAIL не определены. Функция GetMsg, которая получает информацию, возвращаемую сервером по коду, также не определена. Также не определены util.ParseToken(токен) и Claims.ExpiresAt. Итак, мы должны создать новый пакет consts. Мы создаем новый каталог consts в корневом каталоге и создаем новый code.go в каталоге consts, чтобы ввести некоторые определенные константы.Код выглядит следующим образом.

Создайте новый файл const

const (
	SUCCESS        = 200
	ERROR          = 500
	INVALID_PARAMS = 400
)

Создать новый файл сообщения

Создайте новый файл message.go со следующим кодом.

var MsgFlags = map[int]string{
	SUCCESS:                         "ok",
	ERROR:                           "fail",
	INVALID_PARAMS:                  "请求参数错误",
}

func GetMsg(code int) string {
	msg, ok := MsgFlags[code]
	if ok {
		return msg
	}
	return MsgFlags[ERROR]
}

новая утилита

Создайте новый util в корневом каталоге и создайте новый jwt.go под util.Код выглядит следующим образом.

package util

import (
	"github.com/dgrijalva/jwt-go"
	"time"
)

var jwtSecret = []byte(setting.AppSetting.JwtSecret)

type Claims struct {
	Username string `json:"username"`
	Password string `json:"password"`
	jwt.StandardClaims
}

func GenerateToken(username, password string) (string, error) {
	nowTime := time.Now()
	expireTime := nowTime.Add(3 * time.Hour)
	claims := Claims{
		username,
		password,
		jwt.StandardClaims {
			ExpiresAt : expireTime.Unix(),
			Issuer : "go-backend-starter",
		},
	}
	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	token, err := tokenClaims.SignedString(jwtSecret)

	return token, err
}

func ParseToken(token string) (*Claims, error) {
	tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return jwtSecret, nil
	})
	if tokenClaims != nil {
		if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
			return claims, nil
		}
	}

	return nil, err
}

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

В приведенном выше утилите пакет настроек не определен, поэтому на этом этапе нам нужно определить пакет настроек.

Установите зависимости с помощью команды go get.

go get gopkg.in/ini.v1

Создайте новый каталог настроек в корневом каталоге проекта и создайте новый файл settings.go в каталоге настроек.Код выглядит следующим образом.

package setting

import (
	"gopkg.in/ini.v1"
	"log"
)

type App struct {
	JwtSecret string
}
type Server struct {
	Ip   string
	Port string
}
type Database struct {
	Type        string
	User        string
	Password    string
	Host        string
	Name        string
	TablePrefix string
}

var AppSetting = &App{}
var ServerSetting = &Server{}
var DatabaseSetting = &Database{}
var config *ini.File

func Setup() {
	var err error
	config, err = ini.Load("config/app.ini")
	if err != nil {
		log.Fatal("Fail to parse 'config/app.ini': %v", err)
	}
	mapTo("app", AppSetting)
	mapTo("server", ServerSetting)
	mapTo("database", DatabaseSetting)
}

func mapTo(section string, v interface{}) {
	err := config.Section(section).MapTo(v)
	if err != nil {
		log.Fatalf("Cfg.MapTo RedisSetting err: %v", err)
	}
}

Новый файл конфигурации

Создайте новый каталог конфигурации в корневом каталоге проекта и создайте новый файл app.ini со следующим содержимым.

[app]
JwtSecret = 233
[server]
Ip : localhost
Port : 8000
Url : 127.0.0.1:27017
[database]
Type = mysql
User = $YOUR_USERNAME
Password = $YOUR_PASSWORD
Host = 127.0.0.1:3306
Name = golang_test
TablePrefix = golang_test_

Реализовать интерфейс входа

Добавлен интерфейс входа

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

Установите зависимости с помощью команды go get.

go get github.com/astaxie/beego/validation

Создайте новый login.go под роутером, код такой.

package router

import (
	"github.com/astaxie/beego/validation"
	"github.com/detectiveHLH/go-backend-starter/consts"
	"github.com/detectiveHLH/go-backend-starter/util"
	"github.com/gin-gonic/gin"
	"net/http"
)

type auth struct {
	Username string `valid:"Required; MaxSize(50)"`
	Password string `valid:"Required; MaxSize(50)"`
}


func Login(c *gin.Context) {
	appG := util.Gin{C: c}
	valid := validation.Validation{}
	username := c.Query("username")
	password := c.Query("password")

	a := auth{Username: username, Password: password}
	ok, _ := valid.Valid(&a)
	if !ok {
		appG.Response(http.StatusOK, consts.INVALID_PARAMS, nil)
		return
	}

	authService := authentication.Auth{Username: username, Password: password}
	isExist, err := authService.Check()
	if err != nil {
		appG.Response(http.StatusOK, consts.ERROR_AUTH_CHECK_TOKEN_FAIL, nil)
		return
	}

	if !isExist {
		appG.Response(http.StatusOK, consts.ERROR_AUTH, nil)
		return
	}

	token, err := util.GenerateToken(username, password)
	if err != nil {
		appG.Response(http.StatusOK, consts.ERROR_AUTH_TOKEN, nil)
		return
	}

	appG.Response(http.StatusOK, consts.SUCCESS, map[string]string{
		"token": token,
	})
}

Добавлен класс возврата

Добавьте файл response.go в пакет util, код выглядит следующим образом.

package util

import (
	"github.com/detectiveHLH/go-backend-starter/consts"
	"github.com/gin-gonic/gin"
)

type Gin struct {
	C *gin.Context
}

func (g *Gin) Response(httpCode, errCode int, data interface{}) {
	g.C.JSON(httpCode, gin.H{
		"code": httpCode,
		"msg":  consts.GetMsg(errCode),
		"data": data,
	})

	return
}

Добавлена ​​логика аутентификации

В дополнение к возвращаемому классу в login.go есть ключевая логика аутентификации, которая еще не реализована. Создайте новый каталог service/authentication в корневом каталоге и создайте новый файл auth.go в этом каталоге.Код выглядит следующим образом.

package authentication

import "fmt"

type Auth struct {
	Username string
	Password string
}

func (a *Auth) Check() (bool, error) {
	userName := a.Username
	passWord := a.Password
  // todo:实现自己的鉴权逻辑
	fmt.Println(userName, passWord)
	return true, nil
}

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

Изменить router.go

Измените код в router.go следующим образом.

package router

import (
	"github.com/detectiveHLH/go-backend-starter/middleware/jwt"
	"github.com/gin-gonic/gin"
)

func InitRouter() *gin.Engine {
	router := gin.New()

	router.GET("/login", Login)
	apiVersionOne := router.Group("/api/v1/")
  
	apiVersionOne.Use(jwt.Jwt())
  
	apiVersionOne.GET("hello", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"success": true,
			"code": 200,
			"message": "This works",
			"data": nil,
		})
	})
	return router
}

Как видите, мы добавили интерфейс /login в файл маршрутизации и использовали наше промежуточное ПО для аутентификации jwt. Пока это маршрут под v1, он войдет в jwt для аутентификации перед запросом и может продолжить выполнение после прохождения аутентификации.

запустить main.go

Пока что мы используемgo run main.goзапустить сервер, получить доступhttp://localhost:8080/api/v1/helloБудет обнаружена следующая ошибка.

{
    "code": 400,
    "data": null,
    "msg": "请求参数错误"
}

Это связано с тем, что мы добавили аутентификацию. Любой интерфейс, требующий аутентификации, должен иметь токен параметра. Чтобы получить токен, вы должны сначала войти в систему. Предположим, что наше имя пользователя — Том, а пароль — 123. Таким образом вызывается интерфейс входа в систему.

http://localhost:8080/login?username=Tom&password=123

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

{
    "code": 200,
    "data": {
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IlRvbSIsInBhc3N3b3JkIjoiMTIzIiwiZXhwIjoxNTYwMTM5MTE3LCJpc3MiOiJnby1iYWNrZW5kLXN0YXJ0ZXIifQ.I-RSi-xVV1Tk_2iBWolF1u94Y7oVBQXnHh6OI2YKJ6U"
    },
    "msg": "ok"
}

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

http://localhost:8080/api/v1/hello?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IlRvbSIsInBhc3N3b3JkIjoiMTIzIiwiZXhwIjoxNTYwMTM5MTE3LCJpc3MiOiJnby1iYWNrZW5kLXN0YXJ0ZXIifQ.I-RSi-xVV1Tk_2iBWolF1u94Y7oVBQXnHh6OI2YKJ6U

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

И здесь я написал токен в параметре запроса, просто для примера.

Представьте чванство

После завершения базовой структуры мы начинаем вводить документацию swagger для интерфейса. Студенты, которые писали на Java, должны быть знакомы с swagger. Документация по API обычно пишется вручную. То есть каждый параметр каждого интерфейса нужно набирать вручную.

В отличие от swagger, swagger может автоматически генерировать для вас документы swagger, только добавляя в интерфейс несколько аннотаций (операций на Java). В го делаем по аннотации, а потом устанавливаемgin-swagger.

Установить зависимости

go get github.com/swaggo/gin-swagger
go get -u github.com/swaggo/gin-swagger/swaggerFiles
go get -u github.com/swaggo/swag/cmd/swag
go get github.com/ugorji/go/codec
go get github.com/alecthomas/template

Внедрить чванство в роутер

После введения зависимостей нам нужно внедрить swagger в router/router.go. добавить в импорт_ "github.com/detectiveHLH/go-backend-starter/docs".

И вrouter := gin.New()Затем добавьте следующий код.

router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

Пишите аннотации swagger для интерфейсов

Добавьте следующий комментарий над функцией входа в router/login.go.

// @Summary 登录
// @Produce  json
// @Param username query string true "username"
// @Param password query string true "password"
// @Success 200 {string} json "{"code":200,"data":{},"msg":"ok"}"
// @Router /login [get]

Инициализировать чванство

Использовать в корневом каталоге проектаswag initКоманда для инициализации документации swagger. Эта команда создаст каталог docs в корневом каталоге проекта со следующим содержимым.

.
├── docs.go
├── swagger.json
└── swagger.yaml

Посмотреть документацию по чванству

Запустите main.go, а затем зайдите в браузереhttp://localhost:8080/swagger/index.htmlВы можете увидеть документацию API, автоматически сгенерированную swagger на основе аннотаций.

Представляем Бесконечный

Установить бесконечный

go get github.com/fvbock/endless

Изменить main.go

package main

import (
	"fmt"
	"github.com/detectiveHLH/go-backend-starter/router"
	"github.com/fvbock/endless"
	"log"
	"syscall"
)

func main() {
	r := router.InitRouter()

  address := fmt.Sprintf("%s:%s", setting.ServerSetting.Ip, setting.ServerSetting.Port)
	server := endless.NewServer(address, r)
	server.BeforeBegin = func(add string) {
		log.Printf("Actual pid is %d", syscall.Getpid())
	}

  err := server.ListenAndServe()
	if err != nil {
		log.Printf("Server err: %v", err)
	}
}

написать на обороте

По сравнению с управлением зависимостями без модуля go текущий модуль go больше похож на package.json в Node.js и pom.xml в Java, единственное отличие состоит в том, что pom.xml нужно обновлять вручную.

Когда мы получаем проект с модулем go, нам не нужно беспокоиться о некоторых проблемах совместимости, которые могут быть вызваны проблемами версии, когда мы полагаемся на него. Непосредственно используйте команду в моде go для установки всех зависимостей указанной версии, эффект аналогичен тому, что в Node.jsnpm install.

Способ, которым модуль go находит модуль, аналогичен логике Node.js, ищущей зависимости: Node запускается из каталога, в котором выполняется текущая команда, а затем проверяет, есть ли эта зависимость в node_modules, пока не будет найдена. . Go, в свою очередь, ищет файл go.mod, чтобы найти модуль.

Я верю, что управление зависимостями после go будет становиться все лучше и лучше.

Happy hacking.

Ссылаться на:

Прошлые статьи:

Связанный:

  • Персональный сайт:Lunhao Hu
  • Официальная учетная запись WeChat: заметки о полном стеке SH (или прямой поиск WeChat LunhaoHu в интерфейсе добавления официальной учетной записи)