本期透過新增檔案上傳功能、使用 Makefile
簡化開發以及實現優雅的伺服器關閉來完善我們的 Go 驗證伺服器。 這可以防止突然終止並確保所有正在進行的任務在伺服器停止之前完成。
正常關閉實施
新的cmd/api/server.go
檔案集中了伺服器管理。 Goroutine 監視終止訊號(SIGINT、SIGTERM)。收到信號後,它會正常關閉伺服器。 評論闡明了每個步驟。
package main import ( "context" "errors" "fmt" "net/http" "os" "os/signal" "syscall" "time" ) // ... (Existing application code) ... func (app *application) serve(router http.Handler) error { // Server initialization with timeouts for idle, read, and write operations. srv := &http.Server{ Addr: fmt.Sprintf(":%d", app.config.port), Handler: app.recoverPanic(app.authenticate(router)), IdleTimeout: time.Minute, ReadTimeout: 10 * time.Second, WriteTimeout: 30 * time.Second, } // Channel to manage errors during shutdown. shutdownError := make(chan error) // Goroutine to listen for termination signals and initiate graceful shutdown. go func() { quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) s := <-quit // Wait for signal fmt.Println("Shutting down server...") // Context with timeout for graceful shutdown. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Attempt graceful shutdown. shutdownError <- srv.Shutdown(ctx) }() // Start the server and report any errors. fmt.Printf("Starting server on port %d\n", app.config.port) err := srv.ListenAndServe() if !errors.Is(err, http.ErrServerClosed) { return fmt.Errorf("server error: %w", err) } return <-shutdownError } // ... (Rest of application code) ...
在 main.go
中,將 srv.ListenAndServe()
區塊替換為 err = app.serve(router); if err != nil { logger.Fatal(err, nil) }
。 測試涉及使用重試機制(刪除連續重試的憑證)並使用 Ctrl C 中斷伺服器;它應該等待重試完成後再關閉。
使用 Makefile 自動化任務
A Makefile
自動執行重複指令。 將以下內容加入項目的 Makefile
中:
# Include variables from the .envrc file include .envrc ## help: print this help message .PHONY: help help: @echo 'Usage:' @sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /' .PHONY: confirm confirm: @echo -n 'Are you sure? [y/N] ' && read ans && [ $${ans:-N} = y ] ## run/api: run the cmd/api application .PHONY: run/api run/api: go run ./cmd/api ## db/psql: connect to the database using psql .PHONY: db/psql db/psql: psql ${GREENLIGHT_DB_DSN} ## db/migrations/new name=: create a new database migration .PHONY: db/migrations/new db/migrations/new: @echo "Migrating ${name}" migrate create -seq -ext=.sql -dir=./migrations ${name} ## db/migrations/up: apply all up database migrations .PHONY: db/migrations/up db/migrations/up: confirm @echo "Running migrations" migrate -path=./migrations -database=${GREENLIGHT_DB_DSN} up ## audit: tidy and vendor dependencies and format, vet and test all code .PHONY: audit audit: vendor @echo 'Formatting code...' go fmt ./... @echo 'Vetting code...' go vet ./... staticcheck ./... @echo 'Running tests...' go test -race -vet=off ./... ## vendor: tidy and vendor dependencies .PHONY: vendor vendor: @echo 'Tidying and verifying module dependencies...' go mod tidy go mod verify @echo 'Vendoring dependencies...' go mod vendor ## build/api: build the cmd/api application .PHONY: build/api build/api: @echo 'Building cmd/api...' go build -o=./bin/api ./cmd/api GOOS=linux GOARCH=amd64 go build -o=./bin/linux_amd64/api ./cmd/api
運行 make help
、make run/api
、make db/migrations/new name=my_migration
、make db/migrations/up
、make audit
或 make build/api
等指令。 可以按照此結構添加其他命令。
檔案上傳與追蹤
新的資料庫表格追蹤上傳的檔案:
建立遷移make db/migrations/new name=create-creatives
.
000003_create-creatives.up.sql
:
CREATE TABLE IF NOT EXISTS creatives ( id bigserial PRIMARY KEY, user_id bigint NOT NULL REFERENCES users ON DELETE CASCADE, creative_url text NOT NULL, scheduled_at DATE NOT NULL, created_at timestamp(0) with time zone NOT NULL DEFAULT NOW() );
000003_create-creatives.down.sql
:
DROP TABLE IF EXISTS creatives;
internal/data/creatives.go
:
package data import ( "context" "database/sql" "time" "github.com/lib/pq" ) // ... (Creative struct and CreativeModel struct) ... func (c *CreativeModel) Insert(creative *Creative) error { query := `INSERT INTO creatives (user_id, creative_url, scheduled_at) VALUES (, , ) RETURNING id, created_at` ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() args := []interface{}{creative.UserID, creative.CreativeURL, creative.ScheduledAt} return c.DB.QueryRowContext(ctx, query, args...).Scan(&creative.ID, &creative.CreatedAt) } func (c *CreativeModel) GetScheduledCreatives() (map[string][]Creative, error) { query := ` SELECT id, user_id, creative_url, scheduled_at, created_at FROM creatives WHERE scheduled_at = ANY() ` dates := []time.Time{ time.Now().Truncate(24 * time.Hour), time.Now().AddDate(0, 0, 1).Truncate(24 * time.Hour), } ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() rows, err := c.DB.QueryContext(ctx, query, pq.Array(dates)) if err != nil { return nil, err } defer rows.Close() creatives := map[string][]Creative{ "today": {}, "tomorrow": {}, } for rows.Next() { var creative Creative err := rows.Scan(&creative.ID, &creative.UserID, &creative.CreativeURL, &creative.ScheduledAt, &creative.CreatedAt) if err != nil { return nil, err } if creative.ScheduledAt.Equal(dates[0]) { creatives["today"] = append(creatives["today"], creative) } else if creative.ScheduledAt.Equal(dates[1]) { creatives["tomorrow"] = append(creatives["tomorrow"], creative) } } return creatives, rows.Err() }
cmd/api/creatives.go
:(處理文件上傳和預定廣告素材的檢索)
package main import ( "fmt" "io" "net/http" "os" "path" "strings" "time" "github.com/google/uuid" "github.com/vishaaxl/cheershare/internal/data" ) const MaxFileSize = 10 << 20 // 10MB // ... (Existing code) ... func (app *application) uploadCreativeHandler(w http.ResponseWriter, r *http.Request) { // ... (File upload handling logic) ... } func (app *application) getScheduledCreativesHandler(w http.ResponseWriter, r *http.Request) { // ... (Retrieve scheduled creatives logic) ... }
將以下內容新增至您的 main.go
或伺服器初始化中以建立上傳目錄(如果不存在):
uploadDir := "./uploads" if _, err := os.Stat(uploadDir); os.IsNotExist(err) { err := os.MkdirAll(uploadDir, os.ModePerm) if err != nil { fmt.Println("Unable to create uploads directory:", err) } } router.HandlerFunc(http.MethodPost, "/upload-creative", app.requireAuthenticatedUser(app.uploadCreativeHandler)) router.HandlerFunc(http.MethodGet, "/scheduled", app.requireAuthenticatedUser(app.getScheduledCreativesHandler))
請記得將佔位符註解替換為處理程序中文件處理和錯誤管理的實際實作細節。 這完成了核心功能,不包括支付處理(將在未來的更新中涵蓋)。 所提供的第 3 部分連結將被保留。
以上是使用 Go 建置基於 OTP 的身份驗證伺服器:部分檔案上傳和正常關閉的詳細內容。更多資訊請關注PHP中文網其他相關文章!

有效的Go應用錯誤日誌記錄需要平衡細節和性能。 1)使用標準log包簡單但缺乏上下文。 2)logrus提供結構化日誌和自定義字段。 3)zap結合性能和結構化日誌,但需要更多設置。完整的錯誤日誌系統應包括錯誤enrichment、日誌級別、集中式日誌、性能考慮和錯誤處理模式。

EmptyinterfacesinGoareinterfaceswithnomethods,representinganyvalue,andshouldbeusedwhenhandlingunknowndatatypes.1)Theyofferflexibilityforgenericdataprocessing,asseeninthefmtpackage.2)Usethemcautiouslyduetopotentiallossoftypesafetyandperformanceissues,

go'sconcurrencyModelisuniquedUetoItsuseofGoroutinesAndChannels,offeringAlightWeightandefficePappRockhiffcomparredTothread-likeLanguagesLikeLikeJjava,Python,andrust.1)

go'sconcurrencyModeluessgoroutinesandChannelStomanageConconCurrentPrommmengement.1)GoroutinesArightweightThreadThreadSthAtalLeadSthAtalAlaLeasyParalleAftasks,增強Performance.2)ChannelsfacilitatesfacilitatesafeDataTaAexafeDataTaAexchangeBetnegnegoroutinesGoroutinesGoroutinesGoroutinesGoroutines,crucialforsforsynchrroniz

Interfacesand -polymormormormormormingingoenhancecodereusanity和Maintainability.1)defineInterfaceSattherightabStractractionLevel.2)useInterInterFacesFordEffordExpentIndention.3)ProfileCodeTomeAgePerformancemacts。

initiTfunctioningOrunSautomation beforeTheMainFunctionToInitializePackages andSetUptheNvironment.it'susefulforsettingupglobalvariables,資源和performingOne-timesEtepaskSarpaskSacraskSacrastAscacrAssanyPackage.here'shere'shere'shere'shere'shodshowitworks:1)Itcanbebeusedinanananainapthecate,NotjustAckAckAptocakeo

接口組合在Go編程中通過將功能分解為小型、專注的接口來構建複雜抽象。 1)定義Reader、Writer和Closer接口。 2)通過組合這些接口創建如File和NetworkStream的複雜類型。 3)使用ProcessData函數展示如何處理這些組合接口。這種方法增強了代碼的靈活性、可測試性和可重用性,但需注意避免過度碎片化和組合複雜性。

initfunctionsingoareAutomationalCalledBeLedBeForeTheMainFunctionandAreuseFulforSetupButcomeWithChallenges.1)executiondorder:totiernitFunctionSrunIndIndefinitionorder,cancancapationSifsUsiseSiftheyDepplothother.2)測試:sterfunctionsmunctionsmunctionsMayInterfionsMayInterferfereWithTests,b


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能