├── .gitignore ├── README.md ├── adapters └── sql.go ├── api └── db.go ├── cmd ├── config.go └── main.go ├── config.yml ├── docker ├── docker-compose.yaml └── mysql │ └── init.sql ├── go.mod ├── go.sum ├── proto ├── service_example.pb.go ├── service_example.proto └── service_example_grpc.pb.go └── services ├── adapter.go ├── grpc.go ├── init.go ├── repository.go ├── rest.go ├── service_hello.go ├── utils.go └── validation.go /.gitignore: -------------------------------------------------------------------------------- 1 | # These are some examples of commonly ignored file patterns. 2 | # You should customize this list as applicable to your project. 3 | # Learn more about .gitignore: 4 | # https://www.atlassian.com/git/tutorials/saving-changes/gitignore 5 | 6 | # Node artifact files 7 | node_modules/ 8 | dist/ 9 | 10 | # Compiled Java class files 11 | *.class 12 | 13 | # Compiled Python bytecode 14 | *.py[cod] 15 | 16 | # Log files 17 | *.log 18 | 19 | # Package files 20 | *.jar 21 | 22 | # Maven 23 | target/ 24 | dist/ 25 | 26 | # JetBrains IDE 27 | .idea/ 28 | 29 | # Unit test reports 30 | TEST*.xml 31 | 32 | # Generated by MacOS 33 | .DS_Store 34 | 35 | # Generated by Windows 36 | Thumbs.db 37 | 38 | # Applications 39 | *.app 40 | *.exe 41 | *.war 42 | 43 | # Large media files 44 | *.mp4 45 | *.tiff 46 | *.avi 47 | *.flv 48 | *.mov 49 | *.wmv 50 | 51 | # fresh configuration(for local development only) 52 | runner.conf 53 | 54 | # Temporary Files & Folder 55 | tmp/ 56 | 57 | # binary 58 | main -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > **Note** 2 | > 3 | > This repo is a example for this article https://arisharyanto.medium.com/best-way-to-structuring-golang-code-6e619e70ce38 4 | 5 | ## How to Run 6 | 7 | ### Run environment 8 | ```shel 9 | $ docker-compose up -d 10 | ``` 11 | 12 | ### Install GRPC 13 | follow this http://google.github.io/proto-lens/installing-protoc.html to install protobuf in your PC\ 14 | \ 15 | and then run this in you cli 16 | ```shel 17 | $ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest 18 | $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest 19 | ``` 20 | 21 | ### Activate Proto Shell 22 | open bash_profile file 23 | ```shel 24 | $ nano ~/.bash_profile 25 | ``` 26 | 27 | add this code inside 28 | ```shel 29 | export GO_PATH=~/go 30 | export PATH=$PATH:/$GO_PATH/bin 31 | ``` 32 | 33 | then save. 34 | 35 | and then run this 36 | ```shel 37 | $ source ~/.bash_profile 38 | ``` 39 | 40 | ### Generate Your Proto file 41 | ```shel 42 | $ protoc -I./proto --go_out=./proto --go-grpc_out=./proto ./proto/*.proto 43 | ``` 44 | 45 | ### Run the code 46 | ``` 47 | $ go run cmd/*.go 48 | ``` -------------------------------------------------------------------------------- /adapters/sql.go: -------------------------------------------------------------------------------- 1 | package adapters 2 | 3 | import ( 4 | "log" 5 | "time" 6 | 7 | "github.com/Aris-haryanto/Best-Way-To-Structuring-Golang-Code/api" 8 | "github.com/mitchellh/mapstructure" 9 | "gorm.io/driver/mysql" 10 | "gorm.io/gorm" 11 | ) 12 | 13 | type Hello struct { 14 | Name string `gorm:"column:name"` 15 | ID int64 `gorm:"primaryKey"` 16 | } 17 | 18 | type SqlDB struct { 19 | SqlConn *gorm.DB 20 | } 21 | 22 | func SqlConnection(username string, password string, host string, port string) *gorm.DB { 23 | dsn := username + ":" + password + "@tcp(" + host + ":" + port + ")/hello_db?charset=utf8mb4&parseTime=True&loc=Local" 24 | db, connErr := gorm.Open(mysql.Open(dsn), &gorm.Config{}) 25 | 26 | if connErr != nil { 27 | log.Fatalln(connErr) 28 | } 29 | 30 | sqlDB, poolErr := db.DB() 31 | 32 | if poolErr != nil { 33 | log.Fatalln(connErr) 34 | } 35 | 36 | // SetMaxIdleConns sets the maximum number of connections in the idle connection pool. 37 | sqlDB.SetMaxIdleConns(10) 38 | 39 | // SetMaxOpenConns sets the maximum number of open connections to the database. 40 | sqlDB.SetMaxOpenConns(100) 41 | 42 | // SetConnMaxLifetime sets the maximum amount of time a connection may be reused. 43 | sqlDB.SetConnMaxLifetime(time.Hour) 44 | 45 | db.Debug().AutoMigrate(&Hello{}) 46 | 47 | return db 48 | } 49 | 50 | func (sql *SqlDB) CloseSql() { 51 | c, _ := sql.SqlConn.DB() 52 | c.Close() 53 | } 54 | 55 | func (sql *SqlDB) SelectSomething(q *api.QuerySomething) (resp []api.ResponseSomething, err error) { 56 | response := []map[string]interface{}{} 57 | errSql := sql.SqlConn.Model(&Hello{}).Where("name = ?", q.Name).Find(&response) 58 | if errSql.Error != nil { 59 | return resp, errSql.Error 60 | } 61 | 62 | // you need to decode to api struct make it not dependency with the adapter 63 | // so you can change with other DB like a redis, elasticsearch, mongodb 64 | errDecodeToStruct := mapstructure.Decode(response, &resp) 65 | if errDecodeToStruct != nil { 66 | return resp, errDecodeToStruct 67 | } 68 | 69 | return resp, nil 70 | } 71 | -------------------------------------------------------------------------------- /api/db.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | type QuerySomething struct { 4 | Name string 5 | } 6 | type ResponseSomething struct { 7 | Namanya string `json:"namanya" mapstructure:"name"` 8 | } 9 | -------------------------------------------------------------------------------- /cmd/config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "io/ioutil" 6 | "os" 7 | 8 | "github.com/Aris-haryanto/Best-Way-To-Structuring-Golang-Code/services" 9 | "gopkg.in/yaml.v2" 10 | ) 11 | 12 | // Yaml Config 13 | func getConfig(filePath string) (*services.Configs, error) { 14 | config := services.Configs{} 15 | 16 | if _, err := os.Stat(filePath); err != nil { 17 | return &config, errors.New("config path not valid") 18 | } 19 | 20 | data, err := ioutil.ReadFile(filePath) 21 | if err != nil { 22 | return &config, err 23 | } 24 | 25 | err = yaml.Unmarshal([]byte(data), &config) 26 | return &config, err 27 | } 28 | -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net" 7 | "net/http" 8 | "os" 9 | "os/signal" 10 | "time" 11 | 12 | "github.com/Aris-haryanto/Best-Way-To-Structuring-Golang-Code/adapters" 13 | "github.com/Aris-haryanto/Best-Way-To-Structuring-Golang-Code/services" 14 | "google.golang.org/grpc" 15 | "google.golang.org/grpc/reflection" 16 | 17 | "github.com/gin-gonic/gin" 18 | 19 | pb "github.com/Aris-haryanto/Best-Way-To-Structuring-Golang-Code/proto" 20 | ) 21 | 22 | func sqlConn() *adapters.SqlDB { 23 | //define sql connection 24 | sqlMasterConn := adapters.SqlConnection("root", "root", "localhost", "3308") 25 | setSqlMasterConn := &adapters.SqlDB{SqlConn: sqlMasterConn} 26 | return setSqlMasterConn 27 | } 28 | 29 | func main() { 30 | // get config 31 | getConfig, errConfig := getConfig("./config.yml") 32 | if errConfig != nil { 33 | log.Fatalln(errConfig) 34 | } 35 | 36 | //set config to global variable on service package 37 | services.InitConfig(getConfig) 38 | 39 | // initial service 40 | hello := &services.Hello{} 41 | 42 | // set DB management 43 | sqlConn := sqlConn() 44 | hello.SetDB(sqlConn) 45 | 46 | // register http server 47 | srvRest := &services.RestServer{} 48 | srvRest.RegisterHello(hello) 49 | 50 | // register grpc server 51 | srvGrpc := &services.GrpcServer{} 52 | srvGrpc.RegisterHello(hello) 53 | 54 | // ========================== 55 | 56 | rest := runHttpServer("8081", srvRest) 57 | grpc := runGrpcServer("8082", srvGrpc) 58 | 59 | // Wait for interrupt signal to gracefully shutdown the server with 60 | // a timeout of 5 seconds. 61 | quit := make(chan os.Signal) 62 | signal.Notify(quit, os.Interrupt) 63 | <-quit 64 | log.Println("Shutdown Server ...") 65 | 66 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 67 | 68 | // close everything in here 69 | // like a connection, channel, or anything 70 | defer func() { 71 | cancel() 72 | sqlConn.CloseSql() 73 | }() 74 | 75 | grpc.GracefulStop() 76 | if err := rest.Shutdown(ctx); err != nil { 77 | log.Fatal("Server Shutdown: ", err) 78 | } 79 | 80 | log.Println("Server exiting!") 81 | 82 | } 83 | 84 | func addRoutes(r *gin.Engine, srvRest *services.RestServer) { 85 | r.GET("/hello", func(c *gin.Context) { 86 | ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) 87 | defer cancel() 88 | 89 | // call service method 90 | srvRest.SayHello(ctx, c.Writer, c.Request) 91 | }) 92 | } 93 | 94 | func runHttpServer(port string, srvRest *services.RestServer) *http.Server { 95 | 96 | // define gin 97 | r := gin.Default() 98 | r.Use(gin.Recovery()) 99 | 100 | // add routes to gin 101 | addRoutes(r, srvRest) 102 | 103 | // listen and serve on 0.0.0.0:8080 104 | srv := &http.Server{ 105 | Addr: ":" + port, 106 | Handler: r, 107 | } 108 | 109 | go func() { 110 | if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { 111 | log.Fatalf("listen: %s\n", err) 112 | } 113 | }() 114 | 115 | return srv 116 | 117 | } 118 | 119 | func runGrpcServer(port string, srvGrpc *services.GrpcServer) *grpc.Server { 120 | listen, err := net.Listen("tcp", ":"+port) 121 | if err != nil { 122 | log.Fatalf("failed to listen: %v", err) 123 | } 124 | 125 | srv := grpc.NewServer() 126 | pb.RegisterGrpcServerServer(srv, srvGrpc) 127 | 128 | reflection.Register(srv) 129 | 130 | log.Printf("server listening at %v", listen.Addr()) 131 | 132 | go func() { 133 | if err := srv.Serve(listen); err != nil { 134 | log.Fatalf("failed to serve: %v", err) 135 | } 136 | }() 137 | 138 | return srv 139 | } 140 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | BASE_URL: https://arindasoft.wordpress.com/ -------------------------------------------------------------------------------- /docker/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | mysql: 4 | container_name: local-mysql 5 | ports: 6 | - '3308:3306' 7 | environment: 8 | - MYSQL_ROOT_PASSWORD=root 9 | image: 'mysql:8.0' 10 | volumes: 11 | - ./mysql:/docker-entrypoint-initdb.d 12 | cap_add: 13 | - SYS_NICE 14 | -------------------------------------------------------------------------------- /docker/mysql/init.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS hello_db; -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Aris-haryanto/Best-Way-To-Structuring-Golang-Code 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.8.1 7 | github.com/mitchellh/mapstructure v1.5.0 8 | google.golang.org/grpc v1.51.0 9 | google.golang.org/protobuf v1.28.0 10 | gopkg.in/yaml.v2 v2.4.0 11 | gorm.io/driver/mysql v1.4.4 12 | gorm.io/gorm v1.24.2 13 | ) 14 | 15 | require ( 16 | github.com/gin-contrib/sse v0.1.0 // indirect 17 | github.com/go-playground/locales v0.14.0 // indirect 18 | github.com/go-playground/universal-translator v0.18.0 // indirect 19 | github.com/go-playground/validator/v10 v10.10.0 // indirect 20 | github.com/go-sql-driver/mysql v1.6.0 // indirect 21 | github.com/goccy/go-json v0.9.7 // indirect 22 | github.com/golang/protobuf v1.5.2 // indirect 23 | github.com/jinzhu/inflection v1.0.0 // indirect 24 | github.com/jinzhu/now v1.1.5 // indirect 25 | github.com/json-iterator/go v1.1.12 // indirect 26 | github.com/leodido/go-urn v1.2.1 // indirect 27 | github.com/mattn/go-isatty v0.0.14 // indirect 28 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 29 | github.com/modern-go/reflect2 v1.0.2 // indirect 30 | github.com/pelletier/go-toml/v2 v2.0.1 // indirect 31 | github.com/ugorji/go/codec v1.2.7 // indirect 32 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect 33 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect 34 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect 35 | golang.org/x/text v0.4.0 // indirect 36 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 37 | ) 38 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 4 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 5 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 8 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 10 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 11 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 12 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 13 | github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= 14 | github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= 15 | github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= 16 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 17 | github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= 18 | github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= 19 | github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= 20 | github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= 21 | github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0= 22 | github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= 23 | github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= 24 | github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 25 | github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= 26 | github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 27 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 28 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 29 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 30 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 31 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 32 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 33 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 34 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 35 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 36 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 37 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 38 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 39 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 40 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 41 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 42 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 43 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 44 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 45 | github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= 46 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 47 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 48 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 49 | github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 50 | github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= 51 | github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 52 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 53 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 54 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 55 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 56 | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 57 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 58 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 59 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 60 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 61 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 62 | github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= 63 | github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= 64 | github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= 65 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 66 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 67 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 68 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 69 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 70 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 71 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 72 | github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= 73 | github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= 74 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 75 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 76 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 77 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 78 | github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 79 | github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= 80 | github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= 81 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 82 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 83 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 84 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 85 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= 86 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 87 | github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= 88 | github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= 89 | github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= 90 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 91 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= 92 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 93 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 94 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 95 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 96 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 97 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 98 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 99 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 100 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 101 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 102 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= 103 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 104 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 105 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 106 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 107 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 108 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 109 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 110 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 111 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 112 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 113 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 114 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= 115 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 116 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 117 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 118 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 119 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 120 | golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= 121 | golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 122 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 123 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 124 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 125 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 126 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 127 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 128 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 129 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 130 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 131 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 132 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 133 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= 134 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 135 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 136 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 137 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 138 | google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= 139 | google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= 140 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 141 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 142 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 143 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 144 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 145 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 146 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 147 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 148 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 149 | google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= 150 | google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 151 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 152 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 153 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 154 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 155 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 156 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 157 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 158 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 159 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 160 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 161 | gorm.io/driver/mysql v1.4.4 h1:MX0K9Qvy0Na4o7qSC/YI7XxqUw5KDw01umqgID+svdQ= 162 | gorm.io/driver/mysql v1.4.4/go.mod h1:BCg8cKI+R0j/rZRQxeKis/forqRwRSYOR8OM3Wo6hOM= 163 | gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= 164 | gorm.io/gorm v1.24.2 h1:9wR6CFD+G8nOusLdvkZelOEhpJVwwHzpQOUM+REd6U0= 165 | gorm.io/gorm v1.24.2/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= 166 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 167 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 168 | -------------------------------------------------------------------------------- /proto/service_example.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.1 4 | // protoc v3.21.9 5 | // source: service_example.proto 6 | 7 | package grpc_server 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | reflect "reflect" 13 | sync "sync" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | type RequestHello struct { 24 | state protoimpl.MessageState 25 | sizeCache protoimpl.SizeCache 26 | unknownFields protoimpl.UnknownFields 27 | 28 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 29 | } 30 | 31 | func (x *RequestHello) Reset() { 32 | *x = RequestHello{} 33 | if protoimpl.UnsafeEnabled { 34 | mi := &file_service_example_proto_msgTypes[0] 35 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 36 | ms.StoreMessageInfo(mi) 37 | } 38 | } 39 | 40 | func (x *RequestHello) String() string { 41 | return protoimpl.X.MessageStringOf(x) 42 | } 43 | 44 | func (*RequestHello) ProtoMessage() {} 45 | 46 | func (x *RequestHello) ProtoReflect() protoreflect.Message { 47 | mi := &file_service_example_proto_msgTypes[0] 48 | if protoimpl.UnsafeEnabled && x != nil { 49 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 50 | if ms.LoadMessageInfo() == nil { 51 | ms.StoreMessageInfo(mi) 52 | } 53 | return ms 54 | } 55 | return mi.MessageOf(x) 56 | } 57 | 58 | // Deprecated: Use RequestHello.ProtoReflect.Descriptor instead. 59 | func (*RequestHello) Descriptor() ([]byte, []int) { 60 | return file_service_example_proto_rawDescGZIP(), []int{0} 61 | } 62 | 63 | func (x *RequestHello) GetName() string { 64 | if x != nil { 65 | return x.Name 66 | } 67 | return "" 68 | } 69 | 70 | type ResponseHello struct { 71 | state protoimpl.MessageState 72 | sizeCache protoimpl.SizeCache 73 | unknownFields protoimpl.UnknownFields 74 | 75 | Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` 76 | Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` 77 | Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` 78 | } 79 | 80 | func (x *ResponseHello) Reset() { 81 | *x = ResponseHello{} 82 | if protoimpl.UnsafeEnabled { 83 | mi := &file_service_example_proto_msgTypes[1] 84 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 85 | ms.StoreMessageInfo(mi) 86 | } 87 | } 88 | 89 | func (x *ResponseHello) String() string { 90 | return protoimpl.X.MessageStringOf(x) 91 | } 92 | 93 | func (*ResponseHello) ProtoMessage() {} 94 | 95 | func (x *ResponseHello) ProtoReflect() protoreflect.Message { 96 | mi := &file_service_example_proto_msgTypes[1] 97 | if protoimpl.UnsafeEnabled && x != nil { 98 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 99 | if ms.LoadMessageInfo() == nil { 100 | ms.StoreMessageInfo(mi) 101 | } 102 | return ms 103 | } 104 | return mi.MessageOf(x) 105 | } 106 | 107 | // Deprecated: Use ResponseHello.ProtoReflect.Descriptor instead. 108 | func (*ResponseHello) Descriptor() ([]byte, []int) { 109 | return file_service_example_proto_rawDescGZIP(), []int{1} 110 | } 111 | 112 | func (x *ResponseHello) GetCode() int32 { 113 | if x != nil { 114 | return x.Code 115 | } 116 | return 0 117 | } 118 | 119 | func (x *ResponseHello) GetMessage() string { 120 | if x != nil { 121 | return x.Message 122 | } 123 | return "" 124 | } 125 | 126 | func (x *ResponseHello) GetData() []byte { 127 | if x != nil { 128 | return x.Data 129 | } 130 | return nil 131 | } 132 | 133 | var File_service_example_proto protoreflect.FileDescriptor 134 | 135 | var file_service_example_proto_rawDesc = []byte{ 136 | 0x0a, 0x15, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 137 | 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x73, 0x65, 138 | 0x72, 0x76, 0x65, 0x72, 0x22, 0x22, 0x0a, 0x0c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 139 | 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 140 | 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x51, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x70, 141 | 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 142 | 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 143 | 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 144 | 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 145 | 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0x53, 0x0a, 0x0a, 0x47, 146 | 0x72, 0x70, 0x63, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 147 | 0x6c, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x12, 0x19, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x73, 148 | 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x6c, 149 | 0x6c, 0x6f, 0x1a, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 150 | 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x00, 151 | 0x42, 0x0f, 0x5a, 0x0d, 0x2e, 0x3b, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 152 | 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 153 | } 154 | 155 | var ( 156 | file_service_example_proto_rawDescOnce sync.Once 157 | file_service_example_proto_rawDescData = file_service_example_proto_rawDesc 158 | ) 159 | 160 | func file_service_example_proto_rawDescGZIP() []byte { 161 | file_service_example_proto_rawDescOnce.Do(func() { 162 | file_service_example_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_example_proto_rawDescData) 163 | }) 164 | return file_service_example_proto_rawDescData 165 | } 166 | 167 | var file_service_example_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 168 | var file_service_example_proto_goTypes = []interface{}{ 169 | (*RequestHello)(nil), // 0: grpc_server.RequestHello 170 | (*ResponseHello)(nil), // 1: grpc_server.ResponseHello 171 | } 172 | var file_service_example_proto_depIdxs = []int32{ 173 | 0, // 0: grpc_server.GrpcServer.HelloWorld:input_type -> grpc_server.RequestHello 174 | 1, // 1: grpc_server.GrpcServer.HelloWorld:output_type -> grpc_server.ResponseHello 175 | 1, // [1:2] is the sub-list for method output_type 176 | 0, // [0:1] is the sub-list for method input_type 177 | 0, // [0:0] is the sub-list for extension type_name 178 | 0, // [0:0] is the sub-list for extension extendee 179 | 0, // [0:0] is the sub-list for field type_name 180 | } 181 | 182 | func init() { file_service_example_proto_init() } 183 | func file_service_example_proto_init() { 184 | if File_service_example_proto != nil { 185 | return 186 | } 187 | if !protoimpl.UnsafeEnabled { 188 | file_service_example_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 189 | switch v := v.(*RequestHello); i { 190 | case 0: 191 | return &v.state 192 | case 1: 193 | return &v.sizeCache 194 | case 2: 195 | return &v.unknownFields 196 | default: 197 | return nil 198 | } 199 | } 200 | file_service_example_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 201 | switch v := v.(*ResponseHello); i { 202 | case 0: 203 | return &v.state 204 | case 1: 205 | return &v.sizeCache 206 | case 2: 207 | return &v.unknownFields 208 | default: 209 | return nil 210 | } 211 | } 212 | } 213 | type x struct{} 214 | out := protoimpl.TypeBuilder{ 215 | File: protoimpl.DescBuilder{ 216 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 217 | RawDescriptor: file_service_example_proto_rawDesc, 218 | NumEnums: 0, 219 | NumMessages: 2, 220 | NumExtensions: 0, 221 | NumServices: 1, 222 | }, 223 | GoTypes: file_service_example_proto_goTypes, 224 | DependencyIndexes: file_service_example_proto_depIdxs, 225 | MessageInfos: file_service_example_proto_msgTypes, 226 | }.Build() 227 | File_service_example_proto = out.File 228 | file_service_example_proto_rawDesc = nil 229 | file_service_example_proto_goTypes = nil 230 | file_service_example_proto_depIdxs = nil 231 | } 232 | -------------------------------------------------------------------------------- /proto/service_example.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = ".;grpc_server"; 4 | 5 | package grpc_server; 6 | 7 | message RequestHello { 8 | string name = 1; 9 | } 10 | 11 | // import "google/protobuf/any.proto"; 12 | 13 | message ResponseHello { 14 | int32 code = 1; 15 | string message = 2; 16 | bytes data = 3; 17 | } 18 | 19 | service GrpcServer { 20 | rpc HelloWorld (RequestHello) returns (ResponseHello) {} 21 | } 22 | -------------------------------------------------------------------------------- /proto/service_example_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.21.9 5 | // source: service_example.proto 6 | 7 | package grpc_server 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // GrpcServerClient is the client API for GrpcServer service. 22 | // 23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 24 | type GrpcServerClient interface { 25 | HelloWorld(ctx context.Context, in *RequestHello, opts ...grpc.CallOption) (*ResponseHello, error) 26 | } 27 | 28 | type grpcServerClient struct { 29 | cc grpc.ClientConnInterface 30 | } 31 | 32 | func NewGrpcServerClient(cc grpc.ClientConnInterface) GrpcServerClient { 33 | return &grpcServerClient{cc} 34 | } 35 | 36 | func (c *grpcServerClient) HelloWorld(ctx context.Context, in *RequestHello, opts ...grpc.CallOption) (*ResponseHello, error) { 37 | out := new(ResponseHello) 38 | err := c.cc.Invoke(ctx, "/grpc_server.GrpcServer/HelloWorld", in, out, opts...) 39 | if err != nil { 40 | return nil, err 41 | } 42 | return out, nil 43 | } 44 | 45 | // GrpcServerServer is the server API for GrpcServer service. 46 | // All implementations must embed UnimplementedGrpcServerServer 47 | // for forward compatibility 48 | type GrpcServerServer interface { 49 | HelloWorld(context.Context, *RequestHello) (*ResponseHello, error) 50 | mustEmbedUnimplementedGrpcServerServer() 51 | } 52 | 53 | // UnimplementedGrpcServerServer must be embedded to have forward compatible implementations. 54 | type UnimplementedGrpcServerServer struct { 55 | } 56 | 57 | func (UnimplementedGrpcServerServer) HelloWorld(context.Context, *RequestHello) (*ResponseHello, error) { 58 | return nil, status.Errorf(codes.Unimplemented, "method HelloWorld not implemented") 59 | } 60 | func (UnimplementedGrpcServerServer) mustEmbedUnimplementedGrpcServerServer() {} 61 | 62 | // UnsafeGrpcServerServer may be embedded to opt out of forward compatibility for this service. 63 | // Use of this interface is not recommended, as added methods to GrpcServerServer will 64 | // result in compilation errors. 65 | type UnsafeGrpcServerServer interface { 66 | mustEmbedUnimplementedGrpcServerServer() 67 | } 68 | 69 | func RegisterGrpcServerServer(s grpc.ServiceRegistrar, srv GrpcServerServer) { 70 | s.RegisterService(&GrpcServer_ServiceDesc, srv) 71 | } 72 | 73 | func _GrpcServer_HelloWorld_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 74 | in := new(RequestHello) 75 | if err := dec(in); err != nil { 76 | return nil, err 77 | } 78 | if interceptor == nil { 79 | return srv.(GrpcServerServer).HelloWorld(ctx, in) 80 | } 81 | info := &grpc.UnaryServerInfo{ 82 | Server: srv, 83 | FullMethod: "/grpc_server.GrpcServer/HelloWorld", 84 | } 85 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 86 | return srv.(GrpcServerServer).HelloWorld(ctx, req.(*RequestHello)) 87 | } 88 | return interceptor(ctx, in, info, handler) 89 | } 90 | 91 | // GrpcServer_ServiceDesc is the grpc.ServiceDesc for GrpcServer service. 92 | // It's only intended for direct use with grpc.RegisterService, 93 | // and not to be introspected or modified (even as a copy) 94 | var GrpcServer_ServiceDesc = grpc.ServiceDesc{ 95 | ServiceName: "grpc_server.GrpcServer", 96 | HandlerType: (*GrpcServerServer)(nil), 97 | Methods: []grpc.MethodDesc{ 98 | { 99 | MethodName: "HelloWorld", 100 | Handler: _GrpcServer_HelloWorld_Handler, 101 | }, 102 | }, 103 | Streams: []grpc.StreamDesc{}, 104 | Metadata: "service_example.proto", 105 | } 106 | -------------------------------------------------------------------------------- /services/adapter.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | // this is file for define your interface to adapter 4 | // why we define in service 5 | // like dave cheney said "the consumer should be define the interface" 6 | // this service as a consumer 7 | 8 | import "github.com/Aris-haryanto/Best-Way-To-Structuring-Golang-Code/api" 9 | 10 | type IDB interface { 11 | SelectSomething(q *api.QuerySomething) (resp []api.ResponseSomething, err error) 12 | } 13 | -------------------------------------------------------------------------------- /services/grpc.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | // here's for grpc handler 4 | // same with rest.go, in here only for handler and call logic to specific service you want 5 | // so the service is apart from handler 6 | // you can run both of grpc and rest 7 | 8 | import ( 9 | "context" 10 | "encoding/json" 11 | 12 | pb "github.com/Aris-haryanto/Best-Way-To-Structuring-Golang-Code/proto" 13 | ) 14 | 15 | type GrpcServer struct { 16 | pb.UnimplementedGrpcServerServer 17 | srvHello *Hello 18 | } 19 | 20 | func (grpc *GrpcServer) RegisterHello(acd *Hello) { 21 | grpc.srvHello = acd 22 | } 23 | 24 | func (grpc *GrpcServer) HelloWorld(ctx context.Context, request *pb.RequestHello) (*pb.ResponseHello, error) { 25 | getResp, _ := grpc.srvHello.SaidHello(&requestHello{ 26 | Name: request.Name, 27 | }) 28 | 29 | getAny, _ := json.Marshal(getResp.Data) 30 | return &pb.ResponseHello{Code: getResp.Code, Message: getResp.Message, Data: getAny}, nil 31 | } 32 | -------------------------------------------------------------------------------- /services/init.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import "fmt" 4 | 5 | type Configs struct { 6 | BaseUrl string `yaml:"BASE_URL"` 7 | } 8 | 9 | // define global var with default config 10 | var ( 11 | config *Configs 12 | ) 13 | 14 | // set this from server.go 15 | func InitConfig(conf *Configs) { 16 | config = conf 17 | 18 | fmt.Println(config.BaseUrl) 19 | } 20 | -------------------------------------------------------------------------------- /services/repository.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | // you can also add your repository 4 | // before you call module in adapter like sql or redis, etc. but you have to process them firstly 5 | // remember this is not bussiness logic but more like technical thing 6 | // like when you want to insert data to separate DB first for the SQL second to Elastic or something 7 | // you can do in here 8 | // for bussiness logic you only write in main service file in this example in service_hello.go 9 | 10 | // you dont have to name it repository you can name it with what you want the point is you and your team have to know what this files do 11 | -------------------------------------------------------------------------------- /services/rest.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | // here's a file to handle request from http (rest API) 4 | // this is of routing request from route and call service you need 5 | // the routes, we define in main.go, so he in here we dont care about the framework we use 6 | // you can use gin, mux, echo or something else 7 | 8 | import ( 9 | "context" 10 | "encoding/json" 11 | "fmt" 12 | "io/ioutil" 13 | "log" 14 | "net/http" 15 | ) 16 | 17 | type RestServer struct { 18 | srvHello *Hello 19 | } 20 | 21 | // ==================== 22 | 23 | func (rest *RestServer) RegisterHello(acd *Hello) { 24 | rest.srvHello = acd 25 | } 26 | 27 | // ==================== 28 | 29 | func (rest *RestServer) SayHello(ctx context.Context, w http.ResponseWriter, r *http.Request) { 30 | // read body request 31 | body, err := ioutil.ReadAll(r.Body) 32 | if err != nil { 33 | log.Printf("Error reading body: %v", err) 34 | http.Error(w, "can't read body", http.StatusBadRequest) 35 | return 36 | } 37 | 38 | //set header 39 | w.Header().Add("Content-Type", "application/json") 40 | 41 | // convert request body to struct 42 | request := requestHello{} 43 | if err := json.Unmarshal(body, &request); err != nil { 44 | fmt.Println(err) 45 | w.WriteHeader(http.StatusInternalServerError) 46 | json.NewEncoder(w).Encode(responseHello{Code: 500, Message: err.Error(), Data: []byte{}}) 47 | return 48 | } 49 | 50 | // set response 51 | result, _ := rest.srvHello.SaidHello(&request) 52 | w.WriteHeader(int(result.Code)) 53 | json.NewEncoder(w).Encode(result) 54 | } 55 | -------------------------------------------------------------------------------- /services/service_hello.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/Aris-haryanto/Best-Way-To-Structuring-Golang-Code/api" 7 | ) 8 | 9 | // this file is where you put all bussines logic seperate by file if you have more than one service 10 | // i.e auth/middleware/calculation and many more 11 | 12 | type Hello struct { 13 | db IDB 14 | } 15 | 16 | // here's you should define on main.go to set what DB you use 17 | func (hello *Hello) SetDB(db IDB) { 18 | hello.db = db 19 | } 20 | 21 | // ===================== 22 | 23 | // here's request struct used for a function below 24 | type requestHello struct { 25 | Name string `json:"name"` 26 | } 27 | 28 | // here's response struct used for a function below 29 | type responseHello struct { 30 | Code int32 `json:"code"` 31 | Message string `json:"message"` 32 | Data any `json:"data"` 33 | } 34 | 35 | // this the function who using struct above 36 | // remember you should define struct above the function 37 | // that's make your code easy to read and search 38 | func (hello *Hello) SaidHello(reqHello *requestHello) (responseHello, error) { 39 | getResult, err := hello.db.SelectSomething(&api.QuerySomething{Name: reqHello.Name}) 40 | fmt.Println(getResult) 41 | if err != nil { 42 | return responseHello{Code: 500, Message: "failed " + err.Error(), Data: []byte{}}, err 43 | } 44 | return responseHello{Code: 200, Message: "hello " + reqHello.Name + " with baseUrl : " + config.BaseUrl, Data: getResult}, nil 45 | } 46 | -------------------------------------------------------------------------------- /services/utils.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | // this is utils you can put helpers you need in current package 4 | // don't create package for utils and reuse to other package 5 | -------------------------------------------------------------------------------- /services/validation.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | // here's your validation logic 4 | // you can call from other file in this package 5 | // you can create unit test only to each function 6 | --------------------------------------------------------------------------------