Gin, FerretDB 및 oapi-codegen을 사용하여 블로그 API 구축
이 튜토리얼에서는 Go를 사용하여 간단한 블로그 애플리케이션용 RESTful API를 만드는 과정을 안내합니다. 우리는 다음 기술을 사용할 것입니다:
- Gin: Go용 웹 프레임워크
- FerretDB: MongoDB 호환 데이터베이스
- oapi-codegen: OpenAPI 3.0 사양에서 Go 서버 상용구를 생성하는 도구
목차
- 프로젝트 설정
- API 사양 정의
- 서버 코드 생성
- 데이터베이스 계층 구현
- API 핸들러 구현
- 애플리케이션 실행
- API 테스트
- 결론
프로젝트 설정
먼저 Go 프로젝트를 설정하고 필요한 종속성을 설치해 보겠습니다.
mkdir blog-api cd blog-api go mod init github.com/yourusername/blog-api go get github.com/gin-gonic/gin go get github.com/deepmap/oapi-codegen/cmd/oapi-codegen go get github.com/FerretDB/FerretDB
API 사양 정의
프로젝트 루트에 api.yaml이라는 파일을 생성하고 블로그 API에 대한 OpenAPI 3.0 사양을 정의합니다.
openapi: 3.0.0 info: title: Blog API version: 1.0.0 paths: /posts: get: summary: List all posts responses: '200': description: Successful response content: application/json: schema: type: array items: $ref: '#/components/schemas/Post' post: summary: Create a new post requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/NewPost' responses: '201': description: Created content: application/json: schema: $ref: '#/components/schemas/Post' /posts/{id}: get: summary: Get a post by ID parameters: - name: id in: path required: true schema: type: string responses: '200': description: Successful response content: application/json: schema: $ref: '#/components/schemas/Post' put: summary: Update a post parameters: - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/NewPost' responses: '200': description: Successful response content: application/json: schema: $ref: '#/components/schemas/Post' delete: summary: Delete a post parameters: - name: id in: path required: true schema: type: string responses: '204': description: Successful response components: schemas: Post: type: object properties: id: type: string title: type: string content: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time NewPost: type: object required: - title - content properties: title: type: string content: type: string
서버 코드 생성
이제 oapi-codegen을 사용하여 API 사양에 따라 서버 코드를 생성해 보겠습니다.
oapi-codegen -package api api.yaml > api/api.go
이 명령은 api라는 새 디렉토리를 생성하고 서버 인터페이스와 모델이 포함된 api.go 파일을 생성합니다.
데이터베이스 계층 구현
FerretDB를 사용하여 데이터베이스 계층을 구현하려면 db/db.go라는 새 파일을 생성하세요.
package db import ( "context" "time" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) type Post struct { ID primitive.ObjectID `bson:"_id,omitempty"` Title string `bson:"title"` Content string `bson:"content"` CreatedAt time.Time `bson:"createdAt"` UpdatedAt time.Time `bson:"updatedAt"` } type DB struct { client *mongo.Client posts *mongo.Collection } func NewDB(uri string) (*DB, error) { client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(uri)) if err != nil { return nil, err } db := client.Database("blog") posts := db.Collection("posts") return &DB{ client: client, posts: posts, }, nil } func (db *DB) Close() error { return db.client.Disconnect(context.Background()) } func (db *DB) CreatePost(title, content string) (*Post, error) { post := &Post{ Title: title, Content: content, CreatedAt: time.Now(), UpdatedAt: time.Now(), } result, err := db.posts.InsertOne(context.Background(), post) if err != nil { return nil, err } post.ID = result.InsertedID.(primitive.ObjectID) return post, nil } func (db *DB) GetPost(id string) (*Post, error) { objectID, err := primitive.ObjectIDFromHex(id) if err != nil { return nil, err } var post Post err = db.posts.FindOne(context.Background(), bson.M{"_id": objectID}).Decode(&post) if err != nil { return nil, err } return &post, nil } func (db *DB) UpdatePost(id, title, content string) (*Post, error) { objectID, err := primitive.ObjectIDFromHex(id) if err != nil { return nil, err } update := bson.M{ "$set": bson.M{ "title": title, "content": content, "updatedAt": time.Now(), }, } var post Post err = db.posts.FindOneAndUpdate( context.Background(), bson.M{"_id": objectID}, update, options.FindOneAndUpdate().SetReturnDocument(options.After), ).Decode(&post) if err != nil { return nil, err } return &post, nil } func (db *DB) DeletePost(id string) error { objectID, err := primitive.ObjectIDFromHex(id) if err != nil { return err } _, err = db.posts.DeleteOne(context.Background(), bson.M{"_id": objectID}) return err } func (db *DB) ListPosts() ([]*Post, error) { cursor, err := db.posts.Find(context.Background(), bson.M{}) if err != nil { return nil, err } defer cursor.Close(context.Background()) var posts []*Post for cursor.Next(context.Background()) { var post Post if err := cursor.Decode(&post); err != nil { return nil, err } posts = append(posts, &post) } return posts, nil }
API 핸들러 구현
API 핸들러를 구현하려면 handlers/handlers.go라는 새 파일을 생성하세요.
package handlers import ( "net/http" "time" "github.com/gin-gonic/gin" "github.com/yourusername/blog-api/api" "github.com/yourusername/blog-api/db" ) type BlogAPI struct { db *db.DB } func NewBlogAPI(db *db.DB) *BlogAPI { return &BlogAPI{db: db} } func (b *BlogAPI) ListPosts(c *gin.Context) { posts, err := b.db.ListPosts() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } apiPosts := make([]api.Post, len(posts)) for i, post := range posts { apiPosts[i] = api.Post{ Id: post.ID.Hex(), Title: post.Title, Content: post.Content, CreatedAt: post.CreatedAt, UpdatedAt: post.UpdatedAt, } } c.JSON(http.StatusOK, apiPosts) } func (b *BlogAPI) CreatePost(c *gin.Context) { var newPost api.NewPost if err := c.ShouldBindJSON(&newPost); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } post, err := b.db.CreatePost(newPost.Title, newPost.Content) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, api.Post{ Id: post.ID.Hex(), Title: post.Title, Content: post.Content, CreatedAt: post.CreatedAt, UpdatedAt: post.UpdatedAt, }) } func (b *BlogAPI) GetPost(c *gin.Context) { id := c.Param("id") post, err := b.db.GetPost(id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Post not found"}) return } c.JSON(http.StatusOK, api.Post{ Id: post.ID.Hex(), Title: post.Title, Content: post.Content, CreatedAt: post.CreatedAt, UpdatedAt: post.UpdatedAt, }) } func (b *BlogAPI) UpdatePost(c *gin.Context) { id := c.Param("id") var updatePost api.NewPost if err := c.ShouldBindJSON(&updatePost); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } post, err := b.db.UpdatePost(id, updatePost.Title, updatePost.Content) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Post not found"}) return } c.JSON(http.StatusOK, api.Post{ Id: post.ID.Hex(), Title: post.Title, Content: post.Content, CreatedAt: post.CreatedAt, UpdatedAt: post.UpdatedAt, }) } func (b *BlogAPI) DeletePost(c *gin.Context) { id := c.Param("id") err := b.db.DeletePost(id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Post not found"}) return } c.Status(http.StatusNoContent) }
애플리케이션 실행
프로젝트 루트에 main.go라는 새 파일을 생성하여 애플리케이션을 설정하고 실행합니다.
package main import ( "log" "github.com/gin-gonic/gin" "github.com/yourusername/blog-api/api" "github.com/yourusername/blog-api/db" "github.com/yourusername/blog-api/handlers" ) func main() { // Initialize the database connection database, err := db.NewDB("mongodb://localhost:27017") if err != nil { log.Fatalf("Failed to connect to the database: %v", err) } defer database.Close() // Create a new Gin router router := gin.Default() // Initialize the BlogAPI handlers blogAPI := handlers.NewBlogAPI(database) // Register the API routes api.RegisterHandlers(router, blogAPI) // Start the server log.Println("Starting server on :8080") if err := router.Run(":8080"); err != nil { log.Fatalf("Failed to start server: %v", err) } }
API 테스트
이제 API가 실행되었으므로 컬 명령을 사용하여 테스트해 보겠습니다.
- 새 게시물 작성:
curl -X POST -H "Content-Type: application/json" -d '{"title":"My First Post","content":"This is the content of my first post."}' http://localhost:8080/posts
- 모든 게시물 나열:
curl http://localhost:8080/posts
- 특정 게시물 가져오기({id}를 실제 게시물 ID로 교체):
curl http://localhost:8080/posts/{id}
- 게시물 업데이트({id}를 실제 게시물 ID로 대체):
curl -X PUT -H "Content-Type: application/json" -d '{"title":"Updated Post","content":"This is the updated content."}' http://localhost:8080/posts/{id}
- 게시물 삭제({id}를 실제 게시물 ID로 대체):
curl -X DELETE http://localhost:8080/posts/{id}
결론
이 튜토리얼에서는 Gin 프레임워크, FerretDB 및 oapi-codegen을 사용하여 간단한 블로그 API를 구축했습니다. 우리는 다음 단계를 다루었습니다:
- 프로젝트 설정 및 종속성 설치
- OpenAPI 3.0을 사용하여 API 사양 정의
- oapi-codegen으로 서버 코드 생성
- FerretDB를 활용한 데이터베이스 계층 구현
- API 핸들러 구현
- 애플리케이션 실행
- curl 명령으로 API 테스트
이 프로젝트에서는 코드 생성 기능과 MongoDB 호환 데이터베이스를 활용하여 Go로 RESTful API를 생성하는 방법을 보여줍니다. 인증, 페이지 매김 및 더 복잡한 쿼리 기능을 추가하여 이 API를 더욱 확장할 수 있습니다.
이 API를 프로덕션 환경에 배포하기 전에 오류를 적절하게 처리하고, 적절한 로깅을 추가하고, 보안 조치를 구현해야 합니다.
도움이 필요하신가요?
어려운 문제에 직면했거나 새로운 아이디어나 프로젝트에 대한 외부 관점이 필요합니까? 제가 도와드릴 수 있어요! 대규모 투자를 하기 전에 기술 개념 증명을 구축하려는 경우나 어려운 문제에 대한 지침이 필요한 경우 제가 도와드리겠습니다.
제공되는 서비스:
- 문제 해결: 혁신적인 솔루션으로 복잡한 문제를 해결합니다.
- 상담: 프로젝트에 대한 전문가의 조언과 신선한 관점을 제공합니다.
- 개념 증명: 아이디어를 테스트하고 검증하기 위한 예비 모델 개발
저와 함께 일하는 데 관심이 있으시면 hangaikevin@gmail.com으로 이메일을 보내주세요.
당신의 도전을 기회로 바꾸세요!
위 내용은 Gin, FerretDB 및 oapi-codegen을 사용하여 블로그 API 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undress AI Tool
무료로 이미지를 벗다

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Stock Market GPT
더 현명한 결정을 위한 AI 기반 투자 연구

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

goprovidessimpleanfilefile handlingsingtheosandbufiopackages.toreadasmallfileentirely, useos.readfile, whithloadsTecontintomemorySafelyAntomatically ManagestomanagesTomanagesFileOperations.forlageFilesorincrementalprocessing, bufio.scannerallows-by-lyiner

Struct {}는 GO의 필드리스 구조로 제로 바이트를 차지하며 데이터가 필요하지 않은 시나리오에서 종종 사용됩니다. Goroutine 동기화와 같은 채널의 신호로 사용됩니다. 2. 효율적인 메모리에서 주요 존재 검사를 달성하기 위해 값 유형의 맵 모음으로 사용됩니다. 3. 종속성 주입 또는 조직 기능에 적합한 정의 가능한 상태없는 방법 수신기. 이 유형은 제어 흐름과 명확한 의도를 표현하는 데 널리 사용됩니다.

gracefulshutdownsingoapplicationseentialsiverforreliable, ac

cgoenablesgotocallccode, clibraries likeopenssl, accesstolow-levelsystemapis, andperformanceoptimization을 허용하는 cgoenablesgotocallccode; cheadersincomments, usesc.function () 신교, 그리고 demandscarefulmorymanagement.hehintect

표준 라이브러리의 인코딩/JSON 패키지를 사용하여 JSON 구성 파일을 읽습니다. 2. yaml 형식 구성을 읽으려면 gopkg.in/yaml.v3 라이브러리를 사용하십시오. 3. os.getenv 또는 Godotenv 라이브러리를 사용하여 파일 구성을 덮어 쓰십시오. 4. Viper 라이브러리를 사용하여 다중 형식 구성, 환경 변수, 자동 재 장전과 같은 고급 기능을 지원합니다. 유형 안전을 보장하기 위해 구조를 정의하고, 파일 및 파싱 오류를 올바르게 처리하고, 구조 태그 매핑 필드를 올바르게 사용하고, 하드 코딩 된 경로를 피하고, 생산 환경에서 환경 변수 또는 안전한 구성 저장을 사용하는 것이 좋습니다. 요구 사항이 복잡 할 때 간단한 JSON으로 시작하여 Viper로 마이그레이션 할 수 있습니다.

이 기사에서는 정수-스트링 변환에 strconv.itoa64를 사용하려고 할 때 GO에서 발생하는 "정의되지 않은"오류를 해결하는 것을 목표로합니다. ITOA64가 존재하지 않는 이유를 설명하고 strconv 패키지의 strconv.formatint에 대한 올바른 대안에 대한 세부 정보를 제공합니다. 인스턴스 코드를 통해 독자는 정수 유형을 지정된 파티션의 문자열 표현으로 효율적이고 정확하게 변환하는 방법을 배우고 일반적인 프로그래밍 트랩을 피하고 코드 견고성 및 가독성을 향상시키는 방법을 배웁니다.

SQLCCLI 도구를 설치하면 컬 스크립트 또는 홈브류를 사용하는 것이 좋습니다. 2. db/schema.sql (테이블 구조), db/query.sql (주석화 된 쿼리) 및 sqlc.yaml 구성 파일을 포함한 프로젝트 구조를 만듭니다. 3. schema.sql에서 데이터베이스 테이블을 정의합니다. 4. -name : annotation and : exec/: one/: query.sqlc.yaml의 많은 지시문; 5. 패키지 경로, 쿼리 파일, 스키마 파일, 데이터베이스 엔진 및 생성 옵션을 지정하도록 sqlc.yaml을 구성합니다. 6. 모델, 쿼리 메소드 및 인터페이스를 포함하여 유형-안전 GO 코드를 생성하려면 sqlcgenerate를 실행합니다.

Marshaljson 및 Unmarshaljson을위한 맞춤형 GO 구조의 JSON 직렬화 및 사막화를 구현하며, 비표준 형식을 처리하거나 이전 데이터와 호환되는 데 적합합니다. 2. 필드 형식 변환과 같은 Marshaljson을 통한 출력 구조를 제어합니다. 3. 사용자 정의 날짜와 같은 Unmarshaljson을 통한 특별 형식 데이터를 구문 분석합니다. 4. 재귀 통화로 인한 무한 루프를 피하고 유형 별명을 사용하여 사용자 정의 방법을 우회하십시오.
