GithubHelp home page GithubHelp logo

gothinkster / golang-gin-realworld-example-app Goto Github PK

View Code? Open in Web Editor NEW
2.4K 50.0 484.0 197 KB

Exemplary real world application built with Golang + Gin

Home Page: https://realworld.io

License: MIT License

Go 98.92% Shell 1.08%
gin golang crud todolist todomvc gorm go gin-mvc example best-practices

golang-gin-realworld-example-app's Introduction

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)

golang-gin-realworld-example-app's People

Contributors

alonski avatar ericsimons avatar esakkiraj avatar itssujan avatar optikfluffel avatar pvillela avatar shola avatar tonyalaribe avatar wangzitian0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

golang-gin-realworld-example-app's Issues

Cannot find package ".../wangzitian0/..."

I'd like to test drive this project locally. I followed the instructions listed on the README.
Tried to run go test -v ./... -cover, but I received this error:

hello.go:9:2: cannot find package "github.com/wangzitian0/golang-gin-starter-kit/articles" in any of:
	/Users/xyz/Programming/Go/projects/src/github.com/gothinkster/golang-gin-realworld-example-app/vendor/github.com/wangzitian0/golang-gin-starter-kit/articles (vendor tree)
	/usr/local/opt/go/libexec/src/github.com/wangzitian0/golang-gin-starter-kit/articles (from $GOROOT)
	/Users/xyz/Programming/Go/projects/src/github.com/wangzitian0/golang-gin-starter-kit/articles (from $GOPATH)
hello.go:10:2: cannot find package "github.com/wangzitian0/golang-gin-starter-kit/common" in any of:
	/Users/xyz/Programming/Go/projects/src/github.com/gothinkster/golang-gin-realworld-example-app/vendor/github.com/wangzitian0/golang-gin-starter-kit/common (vendor tree)
	/usr/local/opt/go/libexec/src/github.com/wangzitian0/golang-gin-starter-kit/common (from $GOROOT)
	/Users/xyz/Programming/Go/projects/src/github.com/wangzitian0/golang-gin-starter-kit/common (from $GOPATH)
hello.go:11:2: cannot find package "github.com/wangzitian0/golang-gin-starter-kit/users" in any of:
	/Users/xyz/Programming/Go/projects/src/github.com/gothinkster/golang-gin-realworld-example-app/vendor/github.com/wangzitian0/golang-gin-starter-kit/users (vendor tree)
	/usr/local/opt/go/libexec/src/github.com/wangzitian0/golang-gin-starter-kit/users (from $GOROOT)
	/Users/xyz/Programming/Go/projects/src/github.com/wangzitian0/golang-gin-starter-kit/users (from $GOPATH)

Why is the hello.go file is referencing a different repo's model here? Was it a incorrect merge? Am I missing something?

Consider adding comments

Hey there! This is great code to go off of but I think it would be more helpful if comments were added to their appropriate places, which is also go fmt compliant. Thoughts?

why using gin.context in serizlizers

hello guys .
i dont understand why all serializers have a *gin.Context in them like these.

type ProfileSerializer struct {
	C *gin.Context
	UserModel
}
type CommentSerializer struct {
	C *gin.Context
	CommentModel
}

More instructions

Right now trying to follow the readme throws several errors. Including golang.org's x crypto is not found (easy ish fix), going to / returns a 404 which might be expected? and running the tests has several failures.

It'd be very awesome to have a where to go from here section in your readme and more complete instructions on how to get the backend to startup successfully.

Use of global variable to store DB connection

I'm currently learning go, and I was looking for material about structuring go applications and found this repository. However, it uses global variable to store connection to DB, which I subjectively don't like. So, I was searching this topic on internet,...

I've found article https://peter.bourgon.org/blog/2017/06/09/theory-of-modern-go.html, which is also is against use of globals, because:

The function invokes a package global database/sql.Conn, to make a query against some unspecified database; a package global ... . All of these operations have side effects that are completely invisible from an inspection of the function signature. There is no way for a caller to predict any of these things will happen, except by reading the function and diving to the definition of all of the globals.

By lifting each of the dependencies into the signature as parameters, we allow readers to accurately model the scope and potential behaviors of the function. The caller knows exactly what the function needs to do its work, and can provide them accordingly.

I've found it via reddit discussion https://www.reddit.com/r/golang/comments/9i7ipd/passing_through_layers_vs_global_variables/, where are another examples how to structure application without using global variables.

So, my questions are:

  • if you were to model a new application/backend/service in GO, and gin, would you use global variable to store connection to DB?
  • if answer is "yes", then why?

I'm asking this, as I want to learn. I'm biased against global variables in all programming languages (except few special cases for low-level system access). However, I might be persuaded to use global variables in go, if it's strongly encouraged as the "right way" to do things.

PS: thank you for taking your time and sharing the example as public git repo.

How to make end to end test?

I'm learning golang and found this great realworld example app with test cases.
But then realize that there is no e2e tests.

How would you make and organize end to end tests in realworld applications?
Could you make an example to show what the folder structure would be?

Thanks 👍🏻

Issue with cyclic dependency

I see that the the ArticleUserModel structure contains a reference to models.User.

That is I get the reference of the author (a user object).

But what if I want to list all the articles written by a given user ? I would need a reference of models.Article in the user model. Wouldn't that cause a cyclic dependency error ?

How can we get around this problem ? Other than extracting the models in a separate package outside both user and article ?

fail after fresh

hello.go:9:2: cannot find package "github.com/wangzitian0/golang-gin-starter-kit/articles" in any of:
/Users/austin/go/src/golang-gin-realworld-example-app/vendor/github.com/wangzitian0/golang-gin-starter-kit/articles (vendor tree)
/usr/local/Cellar/go/1.12.1/libexec/src/github.com/wangzitian0/golang-gin-starter-kit/articles (from $GOROOT)
/Users/austin/go/src/github.com/wangzitian0/golang-gin-starter-kit/articles (from $GOPATH)
hello.go:10:2: cannot find package "github.com/wangzitian0/golang-gin-starter-kit/common" in any of:
/Users/austin/go/src/golang-gin-realworld-example-app/vendor/github.com/wangzitian0/golang-gin-starter-kit/common (vendor tree)
/usr/local/Cellar/go/1.12.1/libexec/src/github.com/wangzitian0/golang-gin-starter-kit/common (from $GOROOT)
/Users/austin/go/src/github.com/wangzitian0/golang-gin-starter-kit/common (from $GOPATH)
hello.go:11:2: cannot find package "github.com/wangzitian0/golang-gin-starter-kit/users" in any of:
/Users/austin/go/src/golang-gin-realworld-example-app/vendor/github.com/wangzitian0/golang-gin-starter-kit/users (vendor tree)
/usr/local/Cellar/go/1.12.1/libexec/src/github.com/wangzitian0/golang-gin-starter-kit/users (from $GOROOT)
/Users/austin/go/src/github.com/wangzitian0/golang-gin-starter-kit/users (from $GOPATH)

fatal error: unexpected signal during runtime execution

Hi,

Thank you for the project! I'm having some problems to start the application. I'm using golang go1.17.2 darwin/amd64 and right after go run hello.go I'm getting the following error:

$ go run hello.go 
[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)

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0xb01dfacedebac1e pc=0x7fff2046bc9e]

runtime stack:
runtime: unexpected return pc for runtime.sigpanic called from 0x7fff2046bc9e
stack: frame={sp:0x7ffeefbff258, fp:0x7ffeefbff2a8} stack=[0x7ffeefb802f8,0x7ffeefbff360)
0x00007ffeefbff158:  0x01007ffeefbff178  0x0000000000000004 
0x00007ffeefbff168:  0x000000000000001f  0x00007fff2046bc9e 
0x00007ffeefbff178:  0x0b01dfacedebac1e  0x0000000000000001 
0x00007ffeefbff188:  0x0000000004036711 <runtime.throw+0x0000000000000071>  0x00007ffeefbff228 
0x00007ffeefbff198:  0x000000000477b752  0x00007ffeefbff1e0 
0x00007ffeefbff1a8:  0x00000000040369c8 <runtime.fatalthrow.func1+0x0000000000000048>  0x0000000004c869c0 
0x00007ffeefbff1b8:  0x0000000000000001  0x0000000000000001 
0x00007ffeefbff1c8:  0x00007ffeefbff228  0x0000000004036711 <runtime.throw+0x0000000000000071> 
0x00007ffeefbff1d8:  0x0000000004c869c0  0x00007ffeefbff218 
0x00007ffeefbff1e8:  0x0000000004036950 <runtime.fatalthrow+0x0000000000000050>  0x00007ffeefbff1f8 
0x00007ffeefbff1f8:  0x0000000004036980 <runtime.fatalthrow.func1+0x0000000000000000>  0x0000000004c869c0 
0x00007ffeefbff208:  0x0000000004036711 <runtime.throw+0x0000000000000071>  0x00007ffeefbff228 
0x00007ffeefbff218:  0x00007ffeefbff248  0x0000000004036711 <runtime.throw+0x0000000000000071> 
0x00007ffeefbff228:  0x00007ffeefbff230  0x0000000004036740 <runtime.throw.func1+0x0000000000000000> 
0x00007ffeefbff238:  0x0000000004782dea  0x000000000000002a 
0x00007ffeefbff248:  0x00007ffeefbff298  0x000000000404bd16 <runtime.sigpanic+0x0000000000000396> 
0x00007ffeefbff258: <0x0000000004782dea  0x0000000000000000 
0x00007ffeefbff268:  0x00007ffeefbff2d8  0x0000000004029626 <runtime.(*mheap).allocSpan+0x0000000000000546> 
0x00007ffeefbff278:  0x000000c0003f0000  0x0000000000002000 
0x00007ffeefbff288:  0x000000c000000008  0x00000000040ac700 <syscall.libc_write_trampoline+0x0000000000000000> 
0x00007ffeefbff298:  0x00007ffeefbff2e0 !0x00007fff2046bc9e 
0x00007ffeefbff2a8: >0x00007ffeefbff2e0  0x0000000004c1c000 
0x00007ffeefbff2b8:  0x00000000000004f3  0x00000000044ad065 <golang.org/x/sys/unix.libc_ioctl_trampoline+0x0000000000000005> 
0x00007ffeefbff2c8:  0x00000000040686df <runtime.syscall+0x000000000000001f>  0x000000c0001b3ca0 
0x00007ffeefbff2d8:  0x00007ffeefbff320  0x000000c0001b3c70 
0x00007ffeefbff2e8:  0x0000000004066550 <runtime.asmcgocall+0x0000000000000070>  0x0000000000000001 
0x00007ffeefbff2f8:  0x000000c0003e2000  0x20000000055a2918 
0x00007ffeefbff308:  0x00007ffeefbff320  0x000000000401bdc5 <runtime.SetFinalizer.func1+0x0000000000000025> 
0x00007ffeefbff318:  0x00000000000003b8  0x000000c0000001a0 
0x00007ffeefbff328:  0x0000000004064669 <runtime.systemstack+0x0000000000000049>  0x0000000000000004 
0x00007ffeefbff338:  0x0000000004852378  0x0000000004c869c0 
0x00007ffeefbff348:  0x00007ffeefbff390  0x0000000004064565 <runtime.mstart+0x0000000000000005> 
0x00007ffeefbff358:  0x000000000406451d <runtime.rt0_go+0x000000000000013d> 
runtime.throw({0x4782dea, 0x0})
        /usr/local/go/src/runtime/panic.go:1198 +0x71
runtime: unexpected return pc for runtime.sigpanic called from 0x7fff2046bc9e
stack: frame={sp:0x7ffeefbff258, fp:0x7ffeefbff2a8} stack=[0x7ffeefb802f8,0x7ffeefbff360)
0x00007ffeefbff158:  0x01007ffeefbff178  0x0000000000000004 
0x00007ffeefbff168:  0x000000000000001f  0x00007fff2046bc9e 
0x00007ffeefbff178:  0x0b01dfacedebac1e  0x0000000000000001 
0x00007ffeefbff188:  0x0000000004036711 <runtime.throw+0x0000000000000071>  0x00007ffeefbff228 
0x00007ffeefbff198:  0x000000000477b752  0x00007ffeefbff1e0 
0x00007ffeefbff1a8:  0x00000000040369c8 <runtime.fatalthrow.func1+0x0000000000000048>  0x0000000004c869c0 
0x00007ffeefbff1b8:  0x0000000000000001  0x0000000000000001 
0x00007ffeefbff1c8:  0x00007ffeefbff228  0x0000000004036711 <runtime.throw+0x0000000000000071> 
0x00007ffeefbff1d8:  0x0000000004c869c0  0x00007ffeefbff218 
0x00007ffeefbff1e8:  0x0000000004036950 <runtime.fatalthrow+0x0000000000000050>  0x00007ffeefbff1f8 
0x00007ffeefbff1f8:  0x0000000004036980 <runtime.fatalthrow.func1+0x0000000000000000>  0x0000000004c869c0 
0x00007ffeefbff208:  0x0000000004036711 <runtime.throw+0x0000000000000071>  0x00007ffeefbff228 
0x00007ffeefbff218:  0x00007ffeefbff248  0x0000000004036711 <runtime.throw+0x0000000000000071> 
0x00007ffeefbff228:  0x00007ffeefbff230  0x0000000004036740 <runtime.throw.func1+0x0000000000000000> 
0x00007ffeefbff238:  0x0000000004782dea  0x000000000000002a 
0x00007ffeefbff248:  0x00007ffeefbff298  0x000000000404bd16 <runtime.sigpanic+0x0000000000000396> 
0x00007ffeefbff258: <0x0000000004782dea  0x0000000000000000 
0x00007ffeefbff268:  0x00007ffeefbff2d8  0x0000000004029626 <runtime.(*mheap).allocSpan+0x0000000000000546> 
0x00007ffeefbff278:  0x000000c0003f0000  0x0000000000002000 
0x00007ffeefbff288:  0x000000c000000008  0x00000000040ac700 <syscall.libc_write_trampoline+0x0000000000000000> 
0x00007ffeefbff298:  0x00007ffeefbff2e0 !0x00007fff2046bc9e 
0x00007ffeefbff2a8: >0x00007ffeefbff2e0  0x0000000004c1c000 
0x00007ffeefbff2b8:  0x00000000000004f3  0x00000000044ad065 <golang.org/x/sys/unix.libc_ioctl_trampoline+0x0000000000000005> 
0x00007ffeefbff2c8:  0x00000000040686df <runtime.syscall+0x000000000000001f>  0x000000c0001b3ca0 
0x00007ffeefbff2d8:  0x00007ffeefbff320  0x000000c0001b3c70 
0x00007ffeefbff2e8:  0x0000000004066550 <runtime.asmcgocall+0x0000000000000070>  0x0000000000000001 
0x00007ffeefbff2f8:  0x000000c0003e2000  0x20000000055a2918 
0x00007ffeefbff308:  0x00007ffeefbff320  0x000000000401bdc5 <runtime.SetFinalizer.func1+0x0000000000000025> 
0x00007ffeefbff318:  0x00000000000003b8  0x000000c0000001a0 
0x00007ffeefbff328:  0x0000000004064669 <runtime.systemstack+0x0000000000000049>  0x0000000000000004 
0x00007ffeefbff338:  0x0000000004852378  0x0000000004c869c0 
0x00007ffeefbff348:  0x00007ffeefbff390  0x0000000004064565 <runtime.mstart+0x0000000000000005> 
0x00007ffeefbff358:  0x000000000406451d <runtime.rt0_go+0x000000000000013d> 
runtime.sigpanic()
        /usr/local/go/src/runtime/signal_unix.go:719 +0x396

goroutine 1 [syscall]:
syscall.syscall(0x44ad060, 0x1, 0x40487413, 0xc0001b3d30)
        /usr/local/go/src/runtime/sys_darwin.go:22 +0x3b fp=0xc0001b3ca0 sp=0xc0001b3c80 pc=0x406319b
syscall.syscall(0x40a74c6, 0x30, 0xc0001b3d58, 0x40a73f8)
        <autogenerated>:1 +0x26 fp=0xc0001b3ce8 sp=0xc0001b3ca0 pc=0x4068ea6
golang.org/x/sys/unix.ioctl(0x4769117, 0x4, 0x1000000000010)
        /Users/d.a.chebakov/go/pkg/mod/golang.org/x/[email protected]/unix/zsyscall_darwin_amd64.go:731 +0x39 fp=0xc0001b3d18 sp=0xc0001b3ce8 pc=0x44accf9
golang.org/x/sys/unix.IoctlGetTermios(...)
        /Users/d.a.chebakov/go/pkg/mod/golang.org/x/[email protected]/unix/ioctl.go:72
github.com/mattn/go-isatty.IsTerminal(0x4769117)
        /Users/d.a.chebakov/go/pkg/mod/github.com/mattn/[email protected]/isatty_bsd.go:10 +0x50 fp=0xc0001b3d88 sp=0xc0001b3d18 pc=0x44ad110
github.com/gin-gonic/gin.LoggerWithWriter({0x485c000, 0xc000010018}, {0x0, 0x0, 0x1})
        /Users/d.a.chebakov/go/pkg/mod/github.com/gin-gonic/[email protected]/logger.go:61 +0xca fp=0xc0001b3df0 sp=0xc0001b3d88 pc=0x44b5c8a
github.com/gin-gonic/gin.Logger(...)
        /Users/d.a.chebakov/go/pkg/mod/github.com/gin-gonic/[email protected]/logger.go:52
github.com/gin-gonic/gin.Default()
        /Users/d.a.chebakov/go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:137 +0x3f fp=0xc0001b3e48 sp=0xc0001b3df0 pc=0x44b2b1f
main.main()
        /Users/d.a.chebakov/Development/golang-gin-realworld-example-app/hello.go:29 +0x94 fp=0xc0001b3f80 sp=0xc0001b3e48 pc=0x45445b4
runtime.main()
        /usr/local/go/src/runtime/proc.go:255 +0x227 fp=0xc0001b3fe0 sp=0xc0001b3f80 pc=0x4038da7
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1581 +0x1 fp=0xc0001b3fe8 sp=0xc0001b3fe0 pc=0x4066841

goroutine 18 [select]:
database/sql.(*DB).connectionOpener(0xc0002965b0, {0x486a1d8, 0xc0003a8a80})
        /usr/local/go/src/database/sql/sql.go:1196 +0x93
created by database/sql.OpenDB
        /usr/local/go/src/database/sql/sql.go:794 +0x188
exit status 2

Why using transaction when query find?

like this:

func FindOneArticle(condition interface{}) (ArticleModel, error) {
	db := common.GetDB()
	var model ArticleModel
	tx := db.Begin()
	tx.Where(condition).First(&model)
	tx.Model(&model).Related(&model.Author, "Author")
	tx.Model(&model.Author).Related(&model.Author.UserModel)
	tx.Model(&model).Related(&model.Tags, "Tags")
	err := tx.Commit().Error
	return model, err
}

Can someone tell me why using transaction in this part?

Can you update packages?

I get an error. Can you update packages?

go get gopkg.in/gin-gonic/gin.v1
can't load package: package gopkg.in/gin-gonic/gin.v1: code in directory ...

Get a users articles

On your articles endpoints, you have the article author which is related to a user.

What if you wanted to add an endpoint to get a users articles?

This structure would result in an import loop issue. How would you solution for this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.