Convert Figma logo to code with AI

gothinkster logogolang-gin-realworld-example-app

Exemplary real world application built with Golang + Gin

2,494
494
2,494
9

Top Related Projects

80,240

"The mother of all demo apps" — Exemplary fullstack Medium.com clone powered by React, Angular, Node, Django, and many more

Exemplary real world application built with React + Redux

ASP.NET Core backend implementation for RealWorld

Example Spring codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld API spec.

Exemplary real world backend API built with Laravel

Quick Overview

The gothinkster/golang-gin-realworld-example-app is a Go implementation of the "RealWorld" backend API spec using the Gin web framework. It serves as a reference for building scalable and maintainable RESTful APIs in Go, following best practices and demonstrating how to structure a Golang web application.

Pros

  • Implements a real-world application, providing practical examples of Go and Gin usage
  • Well-structured codebase with clear separation of concerns
  • Includes authentication, database integration, and API endpoint implementations
  • Follows the RealWorld spec, making it easy to compare with other language/framework implementations

Cons

  • May not cover all edge cases or advanced features of a production-ready application
  • Documentation could be more extensive for newcomers to Go or Gin
  • Some parts of the codebase might benefit from additional comments or explanations
  • Limited test coverage in some areas

Code Examples

  1. Defining a route in Gin:
func (r *articleRouter) Routes() {
    r.router.GET("/", r.articleList)
    r.router.GET("/:slug", r.articleRetrieve)
    r.router.POST("/", middleware.AuthMiddleware(r.authService), r.articleCreate)
    r.router.PUT("/:slug", middleware.AuthMiddleware(r.authService), r.articleUpdate)
    r.router.DELETE("/:slug", middleware.AuthMiddleware(r.authService), r.articleDelete)
}
  1. Handling a request in a controller:
func (r *articleRouter) articleCreate(c *gin.Context) {
    var json articleCreateRequest
    if err := c.ShouldBindJSON(&json); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    userID := c.MustGet("my_user_id").(uint)
    if article, err := r.articleService.CreateArticle(json.Article, userID); err != nil {
        c.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err})
    } else {
        c.JSON(http.StatusCreated, gin.H{"article": article})
    }
}
  1. Database interaction using GORM:
func (as *ArticleService) CreateArticle(article Article, userID uint) (Article, error) {
    tx := as.db.Begin()
    defer func() {
        if r := recover(); r != nil {
            tx.Rollback()
        }
    }()

    if err := tx.Error; err != nil {
        return article, err
    }

    if err := tx.Create(&article).Error; err != nil {
        tx.Rollback()
        return article, err
    }

    return article, tx.Commit().Error
}

Getting Started

To run the application:

  1. Clone the repository:

    git clone https://github.com/gothinkster/golang-gin-realworld-example-app.git
    
  2. Install dependencies:

    go mod download
    
  3. Set up the database (MySQL) and update the connection string in config/config.go

  4. Run the application:

    go run main.go
    

The API will be available at http://localhost:8080.

Competitor Comparisons

80,240

"The mother of all demo apps" — Exemplary fullstack Medium.com clone powered by React, Angular, Node, Django, and many more

Pros of realworld

  • Comprehensive project with multiple frontend and backend implementations
  • Serves as a central hub for various RealWorld examples
  • Provides a standardized spec for consistent implementation across platforms

Cons of realworld

  • May be overwhelming for beginners due to its extensive nature
  • Requires more time to navigate and understand the full project structure
  • Less focused on a single technology stack compared to specific implementations

Code Comparison

golang-gin-realworld-example-app:

func (u *UserModel) Create() error {
    return db.Create(u).Error
}

realworld (JavaScript example):

export function createUser(user) {
  return axios.post('/api/users', { user });
}

The golang-gin-realworld-example-app provides a more specific implementation using Go and Gin, while realworld offers a generic example that can be adapted to various languages and frameworks.

Summary

realworld serves as a comprehensive reference for building real-world applications across multiple platforms, while golang-gin-realworld-example-app focuses on a specific Go implementation using the Gin framework. The choice between them depends on whether you need a broad overview of different implementations or a targeted Go-based solution.

Pros of node-express-realworld-example-app

  • More extensive documentation and setup instructions
  • Larger community and ecosystem around Node.js and Express
  • Better support for asynchronous operations with async/await syntax

Cons of node-express-realworld-example-app

  • Potentially slower performance compared to Go's compiled code
  • Less type safety and compile-time checks than Go
  • Higher memory usage due to Node.js runtime

Code Comparison

node-express-realworld-example-app:

router.post('/users', async (req, res, next) => {
  try {
    const user = await User.create(req.body.user);
    return res.json({user: user.toAuthJSON()});
  } catch(error) {
    return next(error);
  }
});

golang-gin-realworld-example-app:

func Register(c *gin.Context) {
    var user model.User
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(http.StatusUnprocessableEntity, common.NewValidatorError(err))
        return
    }
    if err := user.Register(); err != nil {
        c.JSON(http.StatusUnprocessableEntity, common.NewError("database", err))
        return
    }
    c.JSON(http.StatusCreated, gin.H{"user": user.Serialize()})
}

The Node.js example uses async/await for handling asynchronous operations, while the Go example uses Gin's context and error handling. The Go code is more verbose but provides stronger type checking and error handling.

Exemplary real world application built with React + Redux

Pros of react-redux-realworld-example-app

  • More comprehensive frontend implementation with React and Redux
  • Larger community and ecosystem for React-based applications
  • Better suited for complex, interactive user interfaces

Cons of react-redux-realworld-example-app

  • Steeper learning curve for developers new to React and Redux
  • Potentially slower initial load times compared to server-side rendered applications
  • More client-side processing, which may impact performance on low-end devices

Code Comparison

react-redux-realworld-example-app (JavaScript):

const mapStateToProps = state => ({
  ...state.article,
  currentUser: state.common.currentUser
});

const mapDispatchToProps = dispatch => ({
  onLoad: payload => dispatch({ type: ARTICLE_PAGE_LOADED, payload }),
  onUnload: () => dispatch({ type: ARTICLE_PAGE_UNLOADED })
});

golang-gin-realworld-example-app (Go):

func ArticleCreate(c *gin.Context) {
    articleModelValidator := NewArticleModelValidator()
    if err := articleModelValidator.Bind(c); err != nil {
        c.JSON(http.StatusUnprocessableEntity, common.NewValidatorError(err))
        return
    }
    // ... (additional logic)
}

The React-Redux example showcases state management and component lifecycle, while the Go-Gin example demonstrates server-side routing and request handling. Each approach has its strengths depending on the project requirements and team expertise.

ASP.NET Core backend implementation for RealWorld

Pros of aspnetcore-realworld-example-app

  • More comprehensive documentation and setup instructions
  • Larger community and ecosystem around ASP.NET Core
  • Better integration with Microsoft technologies and Azure cloud services

Cons of aspnetcore-realworld-example-app

  • Potentially higher resource usage compared to the Go implementation
  • Steeper learning curve for developers new to C# and .NET ecosystem
  • Less flexibility in terms of deployment options compared to Go

Code Comparison

aspnetcore-realworld-example-app (C#):

public async Task<IActionResult> GetArticle(string slug)
{
    var article = await _context.Articles
        .Include(x => x.Author)
        .Include(x => x.ArticleTags)
        .ThenInclude(x => x.Tag)
        .FirstOrDefaultAsync(x => x.Slug == slug);
    if (article == null)
        return NotFound();
    return Ok(new { article = await article.ToArticleResponse(_currentUserAccessor.GetCurrentUsername(), _mapper) });
}

golang-gin-realworld-example-app (Go):

func ArticleRetrieve(c *gin.Context) {
    slug := c.Param("slug")
    articleModel, err := article.FindOneArticle(&article.ArticleModel{Slug: slug})
    if err != nil {
        c.JSON(http.StatusNotFound, common.NewError("articles", errors.New("Invalid slug")))
        return
    }
    serializer := ArticleSerializer{c, articleModel}
    c.JSON(http.StatusOK, gin.H{"article": serializer.Response()})
}

The C# code demonstrates more advanced ORM features and includes eager loading, while the Go code is more straightforward but may require additional queries for related data.

Example Spring codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld API spec.

Pros of spring-boot-realworld-example-app

  • More comprehensive test coverage, including integration tests
  • Better documentation and code comments
  • Utilizes Spring Boot's robust ecosystem and dependency injection

Cons of spring-boot-realworld-example-app

  • Larger codebase and potentially higher resource usage
  • Steeper learning curve for developers new to Spring Boot
  • Slower startup time compared to the Go implementation

Code Comparison

spring-boot-realworld-example-app:

@GetMapping("/articles/{slug}")
public ResponseEntity<SingleArticleResponse> getArticle(@PathVariable("slug") String slug) {
    return articleQueryService.findBySlug(slug)
            .map(article -> ResponseEntity.ok(new SingleArticleResponse(article)))
            .orElseThrow(ResourceNotFoundException::new);
}

golang-gin-realworld-example-app:

func ArticleGet(c *gin.Context) {
    slug := c.Param("slug")
    articleModel, err := article.FindOneArticle(&article.ArticleModel{Slug: slug})
    if err != nil {
        c.JSON(http.StatusNotFound, common.NewError("articles", errors.New("Invalid slug")))
        return
    }
    serializer := ArticleSerializer{c, articleModel}
    c.JSON(http.StatusOK, gin.H{"article": serializer.Response()})
}

The Spring Boot example uses annotations and optional types, while the Go example uses explicit error handling and a more procedural approach. The Spring Boot code is more concise but may be less immediately clear to those unfamiliar with the framework.

Exemplary real world backend API built with Laravel

Pros of laravel-realworld-example-app

  • Built with Laravel, a popular PHP framework with extensive documentation and community support
  • Includes built-in authentication and authorization features
  • Offers a more structured and opinionated approach to application development

Cons of laravel-realworld-example-app

  • May have slower performance compared to the Go-based implementation
  • Requires more server resources due to PHP's nature
  • Less suitable for high-concurrency scenarios

Code Comparison

laravel-realworld-example-app (PHP):

public function login(LoginRequest $request)
{
    $credentials = $request->only('email', 'password');

    if (Auth::attempt($credentials)) {
        return $this->respondWithToken(Auth::user()->getRememberToken());
    }

    return $this->respondError('Invalid credentials', 401);
}

golang-gin-realworld-example-app (Go):

func Login(c *gin.Context) {
    var loginValidator LoginValidator

    if err := c.ShouldBindJSON(&loginValidator); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    user, err := FindOneUser(&User{Email: loginValidator.User.Email})
    if err != nil {
        c.JSON(http.StatusForbidden, gin.H{"error": "Invalid email or password"})
        return
    }

    if user.checkPassword(loginValidator.User.Password) != nil {
        c.JSON(http.StatusForbidden, gin.H{"error": "Invalid email or password"})
        return
    }

    serializer := UserSerializer{c, user}
    c.JSON(http.StatusOK, gin.H{"user": serializer.Response()})
}

The Laravel example showcases a more concise login implementation, while the Go version offers more explicit error handling and type safety.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

RealWorld Example App

Build Status codecov License: MIT GoDoc

Golang/Gin codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld spec and API.

This codebase was created to demonstrate a fully fledged fullstack application built with Golang/Gin including CRUD operations, authentication, routing, pagination, and more.

Directory structure

.
├── gorm.db
├── hello.go
├── common
│   ├── utils.go        //small tools function
│   └── database.go     //DB connect manager
├── users
|   ├── models.go       //data models define & DB operation
|   ├── serializers.go  //response computing & format
|   ├── routers.go      //business logic & router binding
|   ├── middlewares.go  //put the before & after logic of handle request
|   └── validators.go   //form/json checker
├── ...
...

Getting started

Install Golang

Make sure you have Go 1.13 or higher installed.

https://golang.org/doc/install

Environment Config

Set-up the standard Go environment variables according to latest guidance (see https://golang.org/doc/install#install).

Install Dependencies

From the project root, run:

go build ./...
go test ./...
go mod tidy

Testing

From the project root, run:

go test ./...

or

go test ./... -cover

or

go test -v ./... -cover

depending on whether you want to see test coverage and how verbose the output you want.

Todo

  • More elegance config
  • Test coverage (common & users 100%, article 0%)
  • ProtoBuf support
  • Code structure optimize (I think some place can use interface)
  • Continuous integration (done)