java調用restful接口,如何用 Go 快速編寫出 HTTP REST API 服務?

 2023-10-22 阅读 35 评论 0

摘要:在本教程中,明白如何用Go語言寫出一個HTTP REST API服務。 作者?|?Aurelie Vache 譯者 |?槐序,責編 | 郭芮 出品 | CSDN(ID:CSDNnews) java調用restful接口。以下為譯文: 學習一門新語言并不容易,但是如果有具體的例子和手

在本教程中,明白如何用Go語言寫出一個HTTP REST API服務。

作者?|?Aurelie Vache

譯者 |?槐序,責編 | 郭芮

出品 | CSDN(ID:CSDNnews)

java調用restful接口。以下為譯文:

學習一門新語言并不容易,但是如果有具體的例子和手把手指導教程,就很容易上手了。因此,我決定編寫一系列分步指導教程。

讓我們使用Go語言的強大功能來編寫一個HTTP REST API 服務。

Go, Go, Go

java post請求 json。首先要做的就是安裝GVM(Go版本管理器),當然還有安裝GO。

要安裝GO,你可以按照官方網站上的安裝步驟進行操作,也可以使用GVM來安裝。對于Go而言,GVM是一個非常實用的版本管理工具,它允許你通過指定所需版本來更新Go的版本。

安裝

Bash:

bash?<?<(curl?-s-S-L?https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

zsh:

zsh?<?<(curl?-s-S-L?https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

java restful接口開發,用法

$?gvm
Usage:?gvm?[command]
Description:
GVM?is?the?Go?Version?Manager
Commands:
version?—?print?the?gvm?version?number
get?—?gets?the?latest?code?(for?debugging)
use?—?select?a?go?version?to?use?(--default?to?set?permanently)
diff?—?view?changes?to?Go?root
help?—?display?this?usage?text
implode?—?completely?remove?gvm
install?—?install?go?versions
uninstall?—?uninstall?go?versions
cross?—?install?go?cross?compilers
linkthis?—?link?this?directory?into?GOPATH
list?—?list?installed?go?versions
listall?—?list?available?versions
alias?—?manage?go?version?aliases
pkgset?—?manage?go?packages?sets
pkgenv?—?edit?the?environment?for?a?package?set

讓我們比較感興趣的GVM 命令是gvm install命令,它的用法如下:

$?gvm?install?[version]?[options]

Go的安裝:

$?gvm?install?go1.13.3?-B
$?gvm?use?go1.13.3?--default

在你的.zshrc或者.bashrc文件中,設置$GOROOT 和 $GOPATH環境變量,下面是一個例子:(原文下面的2 3 4代碼行命令錯誤,少了空格)

?[[?-s"$HOME/.gvm/scripts/gvm"?]]?&&?source"$HOME/.gvm/scripts/gvm"
export?GOPATH=$HOME/go
export?GOBIN=$GOPATH/bin
export?PATH=${PATH}:$GOBIN

以上就是利用版本管理器來安裝GO。現在進入本文章的核心,來創建我們第一個CLI(命令行程序)。

python restful api 框架。

初始化你的APP

現在我們在GitHub中創建一個倉庫(為了共享和開源)。

首先,登錄GitHub網站,單擊倉庫鏈接,創建一個名叫“http-go-server”的倉庫:

然后,在你本地機器上,把這個新建的倉庫克隆(git clone)到你想放的地方。

get和post請求?“放任何我想放的地方?你確定?”

我們會用GO模塊作為依賴項,所以不要忘記在GOPATH目錄外git clone。但事實上,好消息是,從GO 1.13版本開始,我們不需要再擔心這個問題了。Go模塊現在可以在GOPATH目錄下和目錄外使用。

這也是我在本文選擇使用GO 1.13版本的原因。

現在,為了方便找回及同步本地代碼到git倉庫,我們要git clone這個倉庫:

$?git?clone?https://github.com/scraly/http-go-server.git
$?cd?http-go-server

然后初始化go模塊(依賴管理):

$?go?mod?init?github.com/scraly/http-go-server
go:?creating?new?go.mod:?module?github.com.scraly/http-go-server

我們將創建一個簡單的HTTP服務,但是為了代碼組織方面具有良好實踐。因此我們不會將所有的代碼放到main.go文件,我們會創建一個代碼目錄然后管理我們的代碼。

創建下面的文件目錄結構:

.
├──?README.md
├──?bin
├──?doc
├──?go.mod
├──?internal
├──?pkg
│???└──?swagger
└──?scripts

創建一個HTTP服務

現在開始編寫HTTP服務代碼。

Go是一個很強大的語言。其中一個強大的功能就是有許多可用的內置包,例如net/HTTP。在internal/路徑下面創建一個main.go文件,如下所示:

package?main
import?("fmt""html""log""net/http"
)?
func?main()?{http.HandleFunc("/",?func(w?http.ResponseWriter,?r?*http.Request)?{fmt.Fprintf(w,?"Hello,?%q",?html.EscapeString(r.URL.Path))})log.Println("Listening?on?localhost:8080")log.Fatal(http.ListenAndServe(":8080",?nil))
}

這個簡單的例子創建了一個HTTP服務,并監聽端口8080的傳入請求,并在返回到根目錄/。

現在構建我們的應用來測試它,然后啟動應用程序二進制文件:

$?go?run?internal/main.go
2019/10/27?20:53:39?Listening?on?localhost:8080?...

為了測試你的HTTP服務,你可以使用curl命令來測試下 localhost:8080,或者直接用瀏覽器輸入這個URL來測試:

$?curl?localhost:8080
Hello,?"/"%

很好,我們創建了一個小型的HTTP服務,它可以正常運行。

現在我們可以在二進制可執行文件中構建它:

$?go?build?-o?bin/http-go-server?internal/main.go

很好,我們在幾分鐘內完成了,但是我們將在下文深入了解:-)。

使用 Makefile

我不想手動執行每個命令,所以,為了持續改進我們的應用,好的方法就是創建一個Makefile 文件,這樣我們就可以直接通過命令行來構建應用,生成文件,生成swagger文檔,檢查許可證以及執行單元測試和靜態測試。

我們可以在Makefile里面定義好一系列將由make工具執行的任務。

因此,在這個項目中,我創建了一個Makefile文件,大家可以直接下載,這樣就能節約大家的時間。

Makefile:https://raw.githubusercontent.com/scraly/http-go-server/master/Makefile

出于好奇,在Makefile文件中,我們創建幾個指令(targets,可以是目標文件或者執行文件或者標簽)用來執行一個或者多個命令。

總結下來就是,一個指令需要或者不需要依賴文件(prerequisites)都將執行方法(recipe):target: prerequisites。

<TAB> recipe

在我創建的Makefile文件中,一個build指令構建和打包我們的應用為二進制文件,存放到目錄bin/http-go-server下:

##?Build?all?binaries?
build:$(GO)?build?-o?bin/http-go-server?internal/main.go

HTTP Endpoints 定義

現在我們將優化我們的HTTP服務,并使用Swagger,它可以處理我們的HTTP endpoints定義。

什么是Swagger?

Swagger允許你提供符合OpenAPI規范的標準化APIs文檔。

因為有了Swagger應用,使用Swagger標準文件輸入,你可以在最后生成代碼,并且可以為用戶提供HTML格式的API文檔。

如果你想構建一個公共API,請不要猶豫使用Swagger。

Swagger安裝:請參考go-swagger安裝頁面(https://github.com/go-swagger/go-swagger/blob/master/docs/install.md)。

然后,為了檢查該工具在你的系統中正確安裝,你可以檢查Swagger的版本。

$?swagger?version

現在要做的第一件事是在我們的代碼中創建swagger標準文檔:

pkg/swagger/swagger.yml:

consumes:
-?application/json
info:
description:?HTTP?server?in?Go?with?Swagger?endpoints?definition
title:?http-go-server
version:?0.1.0
produces:
-?application/json
schemes:
-?http
swagger:?"2.0"
paths:
/healthz:
get:
operationId:?checkHealth
produces:
-?text/plain
responses:
'200':
description:?OK?message
schema:
type:?string
enum:
-?OK
/hello/{user}:
get:
description:?Returns?a?greeting?to?the?user!
parameters:
-?name:?user
in:?path
type:?string
required:?true
description:?The?name?of?the?user?to?greet.
responses:
200:
description:?Returns?the?greeting.
schema:
type:?string
400:
description:?Invalid?characters?in?"user"?were?provided.

每次修改swagger文件后,一個好的做法是檢查文件的有效性。

為此,我們可以使用swagger validate命令:

$?swagger?validate?pkg/swagger/swagger.yml
2019/10/27?21:14:47
The?swagger?spec?at?"pkg/swagger/swagger.yml"?is?valid?against?swagger?specification?2.0

或者可以使用一個Makefile指令:

$?make?swagger.validate
2019/10/27?21:15:12
The?swagger?spec?at?"pkg/swagger/swagger.yml"?is?valid?against?swagger?specification?2.0

太棒了,我們的Swagger文件是有效的。

現在我們將在HTML文檔中創建Swagger定義。為此,我們可以使用Docker鏡像,該鏡像考慮到了Swagger YAML定義并且返回一個漂亮的HTML頁面。

$?make?swagger.doc

如果你在瀏覽器中打開已經生成的doc/index.html頁面,可以查看HTML endpoints定義:

很好,是具有可讀性的。

歸功于Swagger規范,現在我們可以生成代碼。

為此,我們進入到pkg/swagger/目錄,創建一個gen.go文件,如下所示:

package?swagger
//go:generate?rm?-rf?server
//go:generate?mkdir?-p?server
//go:generate?swagger?generate?server?--quiet?--target?server?--name?hello-api?--spec?swagger.yml?--exclude-main

由于有Makefile,我們可以執行生成swagger go代碼的文件:

$?make?generate
==>?generating?go?code
GOFLAGS=-mod=vendor?go?generate?github.com.scraly/http-go-server/internal?github.com.scraly/http-go-server/pkg/swagger

如下所示,使用一個swagger endpoint定義輸入,生成了很多代碼,這對于HTTP服務器的實現是節省了時間的。

下面使用Swagger編輯main.go文件:

package?main
import?(
"log"
"github.com/go-openapi/loads"
"github.com/scraly/http-go-server/pkg/swagger/server/restapi"
"github.com/scraly/http-go-server/pkg/swagger/server/restapi/operations"
)
func?main()?{//?Initialize?SwaggerswaggerSpec,?err?:=?loads.Analyzed(restapi.SwaggerJSON,?"")if?err?!=?nil?{log.Fatalln(err)}api?:=?operations.NewHelloAPI(swaggerSpec)server?:=?restapi.NewServer(api)defer?server.Shutdown()server.Port?=?8080//?Start?listening?using?having?the?handlers?and?port//?already?set?up.if?err?:=?server.Serve();?err?!=?nil?{log.Fatalln(err)}
}

現在啟動服務:

$?go?run?internal/main.go
2019/10/28?14:27:26?Serving?hello?at?http://[::]:8080

現在我們可以做幾個測試:

$?curl?localhost:8080
{"code":404,"message":"path?/?was?not?found"}%
$?curl?localhost:8080/hello
{"code":404,"message":"path?/hello?was?not?found"}%
$?curl?localhost:8080/hello/aurelie
"operation?GetHelloUser?has?not?yet?been?implemented"

完美,我們的HTTP服務正在應答,甚至告知我們GetHelloUser接口尚未實現,接下來實現它吧!

編輯main.go文件如下所示:

package?main
import?(
"log"
"github.com/go-openapi/loads"
"github.com/go-openapi/runtime/middleware"
"github.com/scraly/http-go-server/pkg/swagger/server/restapi"
"github.com/scraly/http-go-server/pkg/swagger/server/restapi/operations"
)
func?main()?{//?Initialize?SwaggerswaggerSpec,?err?:=?loads.Analyzed(restapi.SwaggerJSON,?"")if?err?!=?nil?{log.Fatalln(err)}api?:=?operations.NewHelloAPI(swaggerSpec)server?:=?restapi.NewServer(api)defer?func()?{if?err?:=?server.Shutdown();?err?!=?nil?{//?error?handlelog.Fatalln(err)}}()server.Port?=?8080//?Implement?the?CheckHealth?handlerapi.CheckHealthHandler?=?operations.CheckHealthHandlerFunc(func(user?operations.CheckHealthParams)?middleware.Responder?{return?operations.NewCheckHealthOK().WithPayload("OK")})//?Implement?the?GetHelloUser?handlerapi.GetHelloUserHandler?=?operations.GetHelloUserHandlerFunc(func(user?operations.GetHelloUserParams)?middleware.Responder?{return?operations.NewGetHelloUserOK().WithPayload("Hello?"?+?user.User?+?"!")})//?Start?server?which?listeningif?err?:=?server.Serve();?err?!=?nil?{log.Fatalln(err)}
}

再來一次,我們重啟服務:

$?go?run?internal/main.go
2019/10/28?21:45:38?Serving?hello?at?http://[::]:8080
$?curl?localhost:8080/hello/aurelie
"Hello?aurelie!"
$?curl?localhost:8080/healthz
OK%

很好,我們有一個遵守OpenAPI規范的HTTP服務和兩個路由:

  • GET/healthz

  • GET/hello/{name}

我們可以到此為止,因為我們的HTTP服務正常工作,但是我們將繼續深入。

我們將在main.go文件(在文件末尾)中,為路由實現增加新函數。

//Health?route?returns?OK
func?Health(operations.CheckHealthParams)?middleware.Responder?{
return?operations.NewCheckHealthOK().WithPayload("OK")
}
//GetHelloUser?returns?Hello?+?your?name
func?GetHelloUser(user?operations.GetHelloUserParams)?middleware.Responder?{
return?operations.NewGetHelloUserOK().WithPayload("Hello?"?+?user.User?+?"!")
}

現在我們只需在主函數中調用這些新函數:

func?main()?{//?Initialize?SwaggerswaggerSpec,?err?:=?loads.Analyzed(restapi.SwaggerJSON,?"")if?err?!=?nil?{log.Fatalln(err)}api?:=?operations.NewHelloAPI(swaggerSpec)server?:=?restapi.NewServer(api)defer?func()?{if?err?:=?server.Shutdown();?err?!=?nil?{//?error?handlelog.Fatalln(err)}}()server.Port?=?8080api.CheckHealthHandler?=?operations.CheckHealthHandlerFunc(Health)api.GetHelloUserHandler?=?operations.GetHelloUserHandlerFunc(GetHelloUser)//?Start?server?which?listeningif?err?:=?server.Serve();?err?!=?nil?{log.Fatalln(err)}
}

和之前一樣,我們測試靜態測試是否通過,以及我們應用是否構建:

$?make?lint.full
==>?linters?(slow)
INFO?[config_reader]?Config?search?paths:?[./?/Users/uidn3817/git/github.com/scraly/http-go-server/internal?/Users/uidn3817/git/github.com/scraly/http-go-server?/Users/uidn3817/git/github.com/scraly?/Users/uidn3817/git/github.com?/Users/uidn3817/git?/Users/uidn3817?/Users?/]
INFO?[config_reader]?Used?config?file?.golangci.yml
INFO?[lintersdb]?Active?13?linters:?[deadcode?errcheck?goimports?golint?govet?ineffassign?maligned?misspell?nakedret?structcheck?typecheck?unconvert?varcheck]
INFO?[loader]?Go?packages?loading?at?mode?load?types?and?syntax?took?1.474090863s
INFO?[loader]?SSA?repr?building?timing:?packages?building?15.964643ms,?total?220.705097ms
INFO?[runner]?worker.4?took?652.824μs?with?stages:?deadcode:?244.82μs,?unconvert:?110.42μs,?errcheck:?102.565μs,?varcheck:?81.099μs,?structcheck:?38.623μs,?maligned:?34.263μs,?nakedret:?22.825μs,?typecheck:?5.339μs
INFO?[runner]?worker.6?took?1.883μs
INFO?[runner]?worker.8?took?2.125μs
INFO?[runner]?worker.5?took?1.040528ms?with?stages:?ineffassign:?1.035173ms
INFO?[runner]?worker.7?took?3.211184ms?with?stages:?goimports:?3.2029ms
INFO?[runner]?worker.3?took?102.06494ms?with?stages:?misspell:?102.056568ms
INFO?[runner]?worker.1?took?120.104406ms?with?stages:?golint:?120.096599ms
INFO?[runner]?worker.2?took?204.48169ms?with?stages:?govet:?204.471908ms
INFO?[runner]?Workers?idle?times:?#1:?84.514968ms,?#3:?86.547645ms,?#4:?203.167851ms,?#5:?202.957443ms,?#6:?203.09743ms,?#7:?201.160969ms,?#8:?202.973757ms
INFO?[runner]?processing?took?18.697μs?with?stages:?max_same_issues:?14.808μs,?skip_dirs:?737ns,?cgo:?498ns,?nolint:?420ns,?filename_unadjuster:?398ns,?max_from_linter:?281ns,?autogenerated_exclude:?172ns,?path_prettifier:?170ns,?identifier_marker:?167ns,?diff:?164ns,?skip_files:?161ns,?replacement_builder:?158ns,?exclude:?156ns,?source_code:?90ns,?max_per_file_from_linter:?81ns,?path_shortener:?79ns,?uniq_by_line:?79ns,?exclude-rules:?78ns
INFO?File?cache?stats:?0?entries?of?total?size?0B
INFO?Memory:?24?samples,?avg?is?248.1MB,?max?is?671.8MB
INFO?Execution?took?2.277787079s

測試靜態代碼

另外一個好的做法是使用linters 分析來做靜態代碼測試。為此,我們可以使用golang-ci工具(Go里的快速linter,比gometaliner好)。

還是因為有了Makefile,你只需要獲取此處我列出的工具,例如golang-cli:

$?make?get.tools

一個好的做法是新建一個.golangci.yml文件來定義我們想要的linter配置。下面是golang-cli配置示例:

run:
modules-download-mode:?vendor
deadline:?10m
issues-exit-code:?1
tests:?true
skip-files:
-?".*\\.pb\\.go$"
-?".*\\.gen\\.go$"
-?"mock_.*\\.go"
linters:
enable:
-?govet?#?check?standard?vet?rules
-?golint?#?check?standard?linting?rules
-?staticcheck#?comprehensive?checks
-?errcheck?#?find?unchecked?errors
-?ineffassign#?find?ineffective?assignments
-?varcheck?#?find?unused?global?variables?and?constants
-?structcheck#?check?for?unused?struct?parameters
-?deadcode?#?find?code?that?is?not?used
-?nakedret?#?check?for?naked?returns
-?goimports?#?fix?import?order
-?misspell?#?check?spelling
-?unconvert?#?remove?unnecessary?conversions
-?maligned?#?check?for?better?memory?usage
disable:
-?goconst?#?check?for?things?that?could?be?replaced?by?constants
-?gocyclo?#?needs?tweaking
-?depguard?#?unused
-?gosec?#?needs?tweaking
-?dupl?#?slow
-?interfacer?#?not?that?useful
-?gosimple?#?part?of?staticcheck
-?unused?#?part?of?staticcheck
-?megacheck?#?part?of?staticcheck
-?lll
fast:?false
output:
format:?colored-line-number
print-issued-lines:?true
print-linter-name:?true
linters-settings:
errcheck:
#?report?about?not?checking?of?errors?in?type?assetions:?`a?:=?b.(MyStruct)`;
#?default?is?false:?such?cases?aren't?reported?by?default.
check-type-assertions:?false
#?report?about?assignment?of?errors?to?blank?identifier:?`num,?_?:=?strconv.Atoi(numStr)`;
#?default?is?false:?such?cases?aren't?reported?by?default.
check-blank:?false
govet:
#?report?about?shadowed?variables
#TODO#?check-shadowing:?true
#?Obtain?type?information?from?installed?(to?$GOPATH/pkg)?package?files:
#?golangci-lint?will?execute?`go?install?-i`?and?`go?test?-i`?for?analyzed?packages
#?before?analyzing?them.
#?Enable?this?option?only?if?all?conditions?are?met:
#?1.?you?use?only?"fast"?linters?(--fast?e.g.):?no?program?loading?occurs
#?2.?you?use?go?>=?1.10
#?3.?you?do?repeated?runs?(false?for?CI)?or?cache?$GOPATH/pkg?or?`go?env?GOCACHE`?dir?in?CI.
use-installed-packages:?false
golint:
min-confidence:?0.8
gofmt:
simplify:?true
gocyclo:
min-complexity:?10
maligned:
suggest-new:?true
dupl:
threshold:?150
goconst:
min-len:?3
min-occurrences:?3
misspell:
locale:?US
lll:
line-length:?140
tab-width:?1
unused:
#?treat?code?as?a?program?(not?a?library)?and?report?unused?exported?identifiers;?default?is?false.
#?XXX:?if?you?enable?this?setting,?unused?will?report?a?lot?of?false-positives?in?text?editors:
#?if?it's?called?for?subdir?of?a?project?it?can't?find?funcs?usages.?All?text?editor?integrations
#?with?golangci-lint?call?it?on?a?directory?with?the?changed?file.
check-exported:?false
unparam:
#?call?graph?construction?algorithm?(cha,?rta).?In?general,?use?cha?for?libraries,
#?and?rta?for?programs?with?main?packages.?Default?is?cha.
algo:?cha
#?Inspect?exported?functions,?default?is?false.?Set?to?true?if?no?external?program/library?imports?your?code.
#?XXX:?if?you?enable?this?setting,?unparam?will?report?a?lot?of?false-positives?in?text?editors:
#?if?it's?called?for?subdir?of?a?project?it?can't?find?external?interfaces.?All?text?editor?integrations
#?with?golangci-lint?call?it?on?a?directory?with?the?changed?file.
check-exported:?false
nakedret:
#?make?an?issue?if?func?has?more?lines?of?code?than?this?setting?and?it?has?naked?returns;?default?is?30
max-func-lines:?30
prealloc:
#?Report?preallocation?suggestions?only?on?simple?loops?that?have?no?returns/breaks/continues/gotos?in?them.
#?True?by?default.
simple:?true
range-loops:?true#?Report?preallocation?suggestions?on?range?loops,?true?by?default
for-loops:?false#?Report?preallocation?suggestions?on?for?loops,?false?by?default
issues:
max-per-linter:?0
max-same:?0
new:?false
exclude-use-default:?false

接下來我們可以檢查代碼是否包含lint錯誤:

$?make?lint.full
==>?linters?(slow)
INFO?[config_reader]?Config?search?paths:?[./?/Users/uidn3817/git/github.com/scraly/http-go-server/internal?/Users/uidn3817/git/github.com/scraly/http-go-server?/Users/uidn3817/git/github.com/scraly?/Users/uidn3817/git/github.com?/Users/uidn3817/git?/Users/uidn3817?/Users?/]
INFO?[config_reader]?Used?config?file?.golangci.yml
INFO?[lintersdb]?Active?13?linters:?[deadcode?errcheck?goimports?golint?govet?ineffassign?maligned?misspell?nakedret?structcheck?typecheck?unconvert?varcheck]
INFO?[loader]?Go?packages?loading?at?mode?load?types?and?syntax?took?1.403040989s
INFO?[loader]?SSA?repr?building?timing:?packages?building?17.446103ms,?total?215.11635ms
INFO?[runner]?worker.1?took?319.338μs?with?stages:?unconvert:?126.709μs,?structcheck:?105.706μs,?varcheck:?80.624μs
INFO?[runner]?worker.8?took?279.76μs?with?stages:?errcheck:?102.203μs,?nakedret:?88.6μs,?deadcode:?54.547μs,?maligned:?22.796μs,?typecheck:?2.416μs
INFO?[runner]?worker.2?took?908ns
INFO?[runner]?worker.7?took?1.424891ms?with?stages:?ineffassign:?1.419068ms
INFO?[runner]?worker.4?took?2.395856ms?with?stages:?goimports:?2.39105ms
INFO?[runner]?worker.6?took?75.843872ms?with?stages:?golint:?75.832987ms
INFO?[runner]?worker.5?took?77.126536ms?with?stages:?misspell:?77.092913ms
INFO?[runner]?worker.3?took?124.506172ms?with?stages:?govet:?124.498137ms
INFO?[runner]?Workers?idle?times:?#1:?124.053298ms,?#2:?123.973576ms,?#4:?122.078696ms,?#5:?47.339761ms,?#6:?48.693713ms,?#7:?122.946009ms,?#8:?124.035904ms
INFO?[runner]?processing?took?19.597μs?with?stages:?max_same_issues:?16.123μs,?cgo:?541ns,?skip_dirs:?493ns,?nolint:?398ns,?max_from_linter:?280ns,?path_prettifier:?179ns,?filename_unadjuster:?172ns,?replacement_builder:?170ns,?autogenerated_exclude:?170ns,?exclude:?164ns,?diff:?162ns,?skip_files:?161ns,?identifier_marker:?150ns,?source_code:?97ns,?path_shortener:?97ns,?max_per_file_from_linter:?82ns,?exclude-rules:?80ns,?uniq_by_line:?78ns
INFO?File?cache?stats:?0?entries?of?total?size?0B
INFO?Memory:?23?samples,?avg?is?255.8MB,?max?is?672.0MB
INFO?Execution?took?2.119246564s

很好,一起都好。

如果你想編輯.golangci.yml文件,請查看golang-ci支持的linters。

檢查許可證

另外一個好的實踐是檢查許可證。

你需要去檢查許可證(你項目依賴項使用的許可證),例如,當你希望你的應用程序或者公司的代碼開源時,為了避免使用被禁的許可證,就要去檢查。

在Go中存在一個名為wwhrd的工具。

首先,我們創建一個名為.wwhrd.yml的文件,來定義選項:

---
blacklist:
-?AGPL-3.0
-?GPL-2.0
-?GPL-3.0
-?CDDL-1.0
whitelist:
-?Apache-2.0
-?MIT
-?NewBSD
-?FreeBSD
-?LGPL-2.1
-?LGPL-3.0
-?ISC
-?MPL-2.0
-?EPL-1.0
-?Unlicense
#?exceptions:
#?-?github.com/davecgh/go-spew/spew/...?#?ISC?License?misrecognized
#?-?github.com/dchest/uniuri?#?https://creativecommons.org/publicdomain/zero/1.0/

在這個wwhrd文件特性中,你可以添加例外項,黑名單和白名單特性。

一個檢查證書的指令已經寫在了Makefile文件中的,因此你只需要執行它即可:

$?make?license
==>?license?check
wwhrd?check
INFO[0000]?Found?Approved?license????????????????????????license=Apache-2.0?package=go.mongodb.org/mongo-driver/bson/primitive
INFO[0000]?Found?Approved?license????????????????????????license=Apache-2.0?package=github.com/go-openapi/swag
INFO[0000]?Found?Approved?license????????????????????????license=NewBSD?package=github.com/PuerkitoBio/purell
INFO[0000]?Found?Approved?license????????????????????????license=Apache-2.0?package=github.com/go-openapi/jsonreference
INFO[0000]?Found?Approved?license????????????????????????license=Apache-2.0?package=go.mongodb.org/mongo-driver/bson/bsoncodec
INFO[0000]?Found?Approved?license????????????????????????license=Apache-2.0?package=github.com/go-openapi/loads
…

很好,沒有許可證問題了。

構建應用

現在,我們可以在一個可執行的二進制文件里構建應用,并測試二進制文件:

$?make?build
go?build?-o?bin/http-go-server?internal/main.go
$?./bin/http-go-server
2019/10/28?21:47:38?Serving?hello?at?http://[::]:8080

非常棒:-)

總結

正如你在這篇文章第一部分看到的一樣,使用net/http包和Gorilla/mux作為路由,可以在幾分鐘或幾秒鐘內創建一個HTTP服務,但是我想向你展示的是,在代碼組織的最佳實踐方面如何一步一步深入。為了符合OpenAPI標準使用了Swagger,還使用一些其他有用的工具。

最后,我們小型的HTTP服務成長了一些,如下代碼目錄結構所示:

.
├──?Makefile
├──?README.md
├──?bin
│???└──?http-go-server
├──?doc
│???└──?index.html
├──?go.mod
├──?go.sum
├──?internal
│???└──?main.go
├──?pkg
│???└──?swagger
│???????├──?gen.go
│???????├──?server
│???????│???└──?restapi
│???????│???????├──?configure_hello.go
│???????│???????├──?doc.go
│???????│???????├──?embedded_spec.go
│???????│???????├──?operations
│???????│???????│???├──?check_health.go
│???????│???????│???├──?check_health_parameters.go
│???????│???????│???├──?check_health_responses.go
│???????│???????│???├──?check_health_urlbuilder.go
│???????│???????│???├──?get_hello_user.go
│???????│???????│???├──?get_hello_user_parameters.go
│???????│???????│???├──?get_hello_user_responses.go
│???????│???????│???├──?get_hello_user_urlbuilder.go
│???????│???????│???└──?hello_api.go
│???????│???????└──?server.go
│???????└──?swagger.yml
├──?scripts
└──?vendor├──…└──?modules.txt
└──?.gitignore
└──?.golangci.yml
└──?.wwhrd.yml

所有的代碼都可以在GitHub倉庫找到:https://github.com/scraly/http-go-server,希望這類文章對你有所幫助。

原文:https://dzone.com/articles/how-to-write-a-http-rest-api-server-in-go-in-minut

本文為 CSDN 翻譯,轉載請注明來源出處。

【End】

2019我為什么建議你學Python?

https://edu.csdn.net/topic/python115?utm_source=csdn_bw

熱 文?推 薦?

?蘋果三星手機被訴輻射超標;淘集集啟動破產清算;Drupal 8.8.0 發布 | 極客頭條

?Wolfram 語言之父 Stephen Wolfram :編程的未來

?勞榮枝潛逃 23 年落網,多虧了它!

?Visual Basic之父回憶往事

?32 歲被裁員,拿完 N+1月工資,我高興地失業了

?后深度學習時代的一大研究熱點?論因果關系及其構建思路

?被嫌棄的互聯網的 “一生”(上)

?實例分析+ 實踐步驟,手把手教你編寫以太坊、EOS智能合約!

點擊閱讀原文,即刻參加調查!

你點的每個“在看”,我都認真當成了喜歡

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/162858.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息