├── .gitignore ├── LICENSE ├── README.md ├── bazel-k8s-envoy └── README.md ├── grpc-predictable-go-interfaces ├── Makefile ├── README.md ├── go.mod ├── go.sum ├── main.go ├── paginator │ └── paginator.go ├── repo │ └── repo.go ├── service │ └── service.go └── transport │ ├── transport.go │ ├── transport.pb.go │ ├── transport.pb.gw.go │ ├── transport.proto │ └── transport_grpc.pb.go ├── grpc-with-business-logic ├── client │ └── main.go ├── go.mod ├── go.sum ├── pb │ ├── order.pb.go │ └── order.proto ├── server │ ├── grpc_server.go │ └── main.go └── service │ └── service.go ├── how-to-bazel ├── generate-code-with-stringer │ ├── .bazelversion │ ├── .gitignore │ ├── BUILD │ ├── README.md │ ├── WORKSPACE │ ├── cst │ │ ├── BUILD │ │ └── cst.go │ ├── go.mod │ ├── go.sum │ └── main.go └── genereate-and-compile-go-code │ ├── .gitignore │ ├── BUILD │ ├── README.md │ ├── WORKSPACE │ ├── cat │ └── BUILD │ ├── go │ └── BUILD │ ├── go_deps.bzl │ └── schema.png ├── ragel ├── Makefile ├── go.mod ├── go.sum ├── machine.go ├── machine.rl ├── machine_test.go └── ragel_suite_test.go ├── simple-grpc-service ├── client │ └── main.go ├── pb │ ├── calc.pb.go │ └── calc.proto └── server │ └── main.go └── wire ├── Makefile ├── app.go ├── go.mod ├── go.sum ├── main.go ├── pb ├── entity.pb.go └── entity.proto ├── repo ├── provider.go └── repo.go ├── rpci └── rpci.go ├── service ├── provider.go └── service.go ├── wire.go └── wire_gen.go /.gitignore: -------------------------------------------------------------------------------- 1 | */client/client 2 | */server/server 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Evgeny Khabarov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Sources for blog posts 2 | * [gRPC API: Easy start](https://ekhabarov.com/2019/11/grpc-api-easy-start/). 3 | * [gRPC API, part 2: Business Logic](https://ekhabarov.com/2019/12/grpc-api-part-2-business-logic/). 4 | * [Dependency Injection: Google Wire](https://ekhabarov.com/2020/06/dependency-injection-google-wire/) 5 | * [Ragel: state machine compiler](https://ekhabarov.com/2021/01/ragel-state-machine-compiler/) 6 | * [Envoy as an API Gateway](https://ekhabarov.com/post/envoy-as-an-api-gateway/) 7 | * [gRPC: predictable Go interfaces](https://ekhabarov.com/post/grpc-predictable-go-interfaces/) 8 | * [How to generate code with Bazel](https://ekhabarov.com/post/how-to-generate-code-with-bazel/) 9 | -------------------------------------------------------------------------------- /bazel-k8s-envoy/README.md: -------------------------------------------------------------------------------- 1 | # MOVED 2 | 3 | [SEE HERE](https://github.com/ekhabarov/bazel-k8s-envoy). 4 | 5 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/Makefile: -------------------------------------------------------------------------------- 1 | proto: 2 | protoc \ 3 | -I ./transport \ 4 | -I $(GOPATH)/pkg/mod/github.com/grpc-ecosystem/grpc-gateway@v1.16.0/third_party/googleapis \ 5 | --go_out ./transport \ 6 | --go_opt paths=source_relative \ 7 | --go-grpc_out ./transport \ 8 | --go-grpc_opt paths=source_relative \ 9 | --grpc-gateway_out ./transport \ 10 | --grpc-gateway_opt paths=source_relative \ 11 | ./transport/transport.proto 12 | 13 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/README.md: -------------------------------------------------------------------------------- 1 | # gRPC: predictable Go interfaces 2 | 3 | ## Run it 4 | 5 | ```shell 6 | % go run . 7 | ``` 8 | 9 | ## Use it 10 | 11 | ```shell 12 | % curl localhost:8080/v1/list?limit=3&page=5 | jq 13 | { 14 | "entities": [ 15 | { 16 | "id": 13, 17 | "name": "entity_13" 18 | }, 19 | { 20 | "id": 14, 21 | "name": "entity_14" 22 | }, 23 | { 24 | "id": 15, 25 | "name": "entity_15" 26 | } 27 | ] 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ekhabarov/blog-code-snippets/grpc-predictable-go-interfces 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/Masterminds/squirrel v1.5.3 7 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0 8 | github.com/jmoiron/sqlx v1.3.5 9 | github.com/mattn/go-sqlite3 v1.14.16 10 | google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 11 | google.golang.org/grpc v1.51.0 12 | google.golang.org/protobuf v1.28.1 13 | ) 14 | 15 | require ( 16 | github.com/golang/protobuf v1.5.2 // indirect 17 | github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect 18 | github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect 19 | golang.org/x/net v0.2.0 // indirect 20 | golang.org/x/sys v0.2.0 // indirect 21 | golang.org/x/text v0.4.0 // indirect 22 | ) 23 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/go.sum: -------------------------------------------------------------------------------- 1 | github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc= 2 | github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= 3 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 4 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= 6 | github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 7 | github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= 8 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 9 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 10 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 11 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 12 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 13 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0 h1:t7uX3JBHdVwAi3G7sSSdbsk8NfgA+LnUS88V/2EKaA0= 14 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0/go.mod h1:4OGVnY4qf2+gw+ssiHbW+pq4mo2yko94YxxMmXZ7jCA= 15 | github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= 16 | github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= 17 | github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= 18 | github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= 19 | github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= 20 | github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= 21 | github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= 22 | github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 23 | github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= 24 | github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= 25 | github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= 26 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 27 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 28 | github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= 29 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 30 | golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= 31 | golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= 32 | golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= 33 | golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 34 | golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= 35 | golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 36 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 37 | google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 h1:jCw9YRd2s40X9Vxi4zKsPRvSPlHWNqadVkpbMsCPzPQ= 38 | google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= 39 | google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= 40 | google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= 41 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 42 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 43 | google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= 44 | google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 45 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "net" 6 | "net/http" 7 | 8 | "github.com/ekhabarov/blog-code-snippets/grpc-predictable-go-interfces/repo" 9 | "github.com/ekhabarov/blog-code-snippets/grpc-predictable-go-interfces/service" 10 | "github.com/ekhabarov/blog-code-snippets/grpc-predictable-go-interfces/transport" 11 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 12 | "google.golang.org/grpc" 13 | "google.golang.org/grpc/credentials/insecure" 14 | 15 | _ "github.com/mattn/go-sqlite3" 16 | ) 17 | 18 | func main() { 19 | lis, err := net.Listen("tcp", ":5001") 20 | must(err) 21 | 22 | s := grpc.NewServer() 23 | 24 | r, err := repo.New() 25 | must(err) 26 | 27 | transport.RegisterMyServiceServer(s, transport.New(service.New(r))) 28 | go func() { 29 | must(s.Serve(lis)) 30 | }() 31 | 32 | conn, err := grpc.DialContext( 33 | context.Background(), 34 | "0.0.0.0:5001", 35 | grpc.WithBlock(), 36 | grpc.WithTransportCredentials(insecure.NewCredentials()), 37 | ) 38 | must(err) 39 | 40 | gwmux := runtime.NewServeMux() 41 | must(transport.RegisterMyServiceHandler(context.Background(), gwmux, conn)) 42 | 43 | gws := &http.Server{ 44 | Addr: ":8080", 45 | Handler: gwmux, 46 | } 47 | 48 | must(gws.ListenAndServe()) 49 | } 50 | 51 | func must(err error) { 52 | if err != nil { 53 | panic(err) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/paginator/paginator.go: -------------------------------------------------------------------------------- 1 | package paginator 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/Masterminds/squirrel" 7 | ) 8 | 9 | type PageLimiter interface { 10 | GetLimit() int32 11 | GetPage() int32 12 | } 13 | 14 | type Applier interface { 15 | Apply(squirrel.SelectBuilder) squirrel.SelectBuilder 16 | } 17 | 18 | type PageLimitApplier interface { 19 | PageLimiter 20 | Applier 21 | } 22 | 23 | type pageLimiter struct { 24 | limit, page int32 25 | } 26 | 27 | func (pl *pageLimiter) GetLimit() int32 { return pl.limit } 28 | func (pl *pageLimiter) GetPage() int32 { return pl.page } 29 | 30 | func (pl *pageLimiter) Apply(q squirrel.SelectBuilder) squirrel.SelectBuilder { 31 | if pl.GetLimit() < 1 { 32 | return q 33 | } 34 | return q. 35 | Limit(uint64(pl.GetLimit())). 36 | Offset((uint64(pl.GetPage()) - 1) * uint64(pl.GetLimit())) 37 | } 38 | 39 | func MustApply(a Applier, q *squirrel.SelectBuilder) error { 40 | if a == nil { 41 | return fmt.Errorf("applier is nil") 42 | } 43 | 44 | if q == nil { 45 | return fmt.Errorf("select builder is nil, nothing to apply to") 46 | } 47 | 48 | *q = a.Apply(*q) 49 | 50 | return nil 51 | } 52 | 53 | func FromRequest(pl PageLimiter) PageLimitApplier { 54 | page := pl.GetPage() 55 | if page < 1 { 56 | page = 1 57 | } 58 | 59 | limit := pl.GetLimit() 60 | if limit < 1 { 61 | limit = 50 62 | } 63 | 64 | return &pageLimiter{limit: limit, page: page} 65 | } 66 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/repo/repo.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/Masterminds/squirrel" 7 | "github.com/ekhabarov/blog-code-snippets/grpc-predictable-go-interfces/paginator" 8 | "github.com/jmoiron/sqlx" 9 | ) 10 | 11 | type Repo interface { 12 | // List runs query with plain page/limit arguments. 13 | List(page, limit int) ([]Entity, error) 14 | 15 | // ListWithApplier runs query with arguments applied by paginator. 16 | // It accepts minimal required argument paginator.Applier. 17 | ListWithApplier(a paginator.Applier) ([]Entity, error) 18 | } 19 | 20 | type Entity struct { 21 | ID int `db:"id"` 22 | Name string `db:"name"` 23 | } 24 | 25 | type repo struct { 26 | db *sqlx.DB 27 | } 28 | 29 | // New initializes in-memory sqlite database. 30 | func New() (Repo, error) { 31 | db, err := sqlx.Open("sqlite3", ":memory:") 32 | if err != nil { 33 | return nil, fmt.Errorf("failed to initialize db: %w", err) 34 | } 35 | 36 | create := `CREATE TABLE IF NOT EXISTS entities ( 37 | id INTEGER NOT NULL PRIMARY KEY, 38 | name TEXT 39 | );` 40 | 41 | if _, err := db.Exec(create); err != nil { 42 | return nil, fmt.Errorf("failed to create a table: %w", err) 43 | } 44 | 45 | for i := 1; i < 100; i++ { 46 | _, err := db.Exec("INSERT INTO entities VALUES(NULL,?);", fmt.Sprintf("entity_%d", i)) 47 | if err != nil { 48 | return nil, fmt.Errorf("failed to insert a row %d: %w", i, err) 49 | } 50 | } 51 | 52 | return &repo{ 53 | db: db, 54 | }, nil 55 | } 56 | 57 | func runQuery(q squirrel.SelectBuilder, db *sqlx.DB) ([]Entity, error) { 58 | sql, _, err := q.ToSql() 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | fmt.Printf("SQL: %s\n===\n", sql) 64 | 65 | var out []Entity 66 | if err := db.Select(&out, sql); err != nil { 67 | return nil, fmt.Errorf("select failed: %w", err) 68 | } 69 | 70 | return out, nil 71 | } 72 | 73 | func (r *repo) List(page int, limit int) ([]Entity, error) { 74 | q := squirrel.Select("*").From("entities") 75 | 76 | if page > 0 { 77 | if limit < 1 { 78 | limit = 5 79 | } 80 | 81 | q = q.Offset((uint64(page) - 1) * uint64(limit)) 82 | } 83 | 84 | if limit > 0 { 85 | q = q.Limit(uint64(limit)) 86 | } 87 | 88 | return runQuery(q, r.db) 89 | } 90 | 91 | func (r *repo) ListWithApplier(a paginator.Applier) ([]Entity, error) { 92 | q := squirrel.Select("*").From("entities") 93 | 94 | if err := paginator.MustApply(a, &q); err != nil { 95 | return nil, err 96 | } 97 | 98 | return runQuery(q, r.db) 99 | } 100 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/ekhabarov/blog-code-snippets/grpc-predictable-go-interfces/paginator" 7 | "github.com/ekhabarov/blog-code-snippets/grpc-predictable-go-interfces/repo" 8 | ) 9 | 10 | type service struct { 11 | repo repo.Repo 12 | } 13 | 14 | type Service interface { 15 | List(page, limit int) ([]repo.Entity, error) 16 | ListWithApplier(a paginator.PageLimitApplier) ([]repo.Entity, error) 17 | } 18 | 19 | func New(r repo.Repo) Service { 20 | return &service{repo: r} 21 | } 22 | 23 | func (s *service) List(page int, limit int) ([]repo.Entity, error) { 24 | // some additional logic, like logger call 25 | log.Printf("List called with page: %d and limit: %d\n", page, limit) 26 | 27 | return s.repo.List(page, limit) 28 | } 29 | 30 | func (s *service) ListWithApplier(pla paginator.PageLimitApplier) ([]repo.Entity, error) { 31 | // some additional logic, like logger call 32 | log.Printf("ListWithApplier called with page: %d and limit: %d\n", pla.GetPage(), pla.GetLimit()) 33 | 34 | return s.repo.ListWithApplier(pla) 35 | } 36 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/transport/transport.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/ekhabarov/blog-code-snippets/grpc-predictable-go-interfces/paginator" 7 | "github.com/ekhabarov/blog-code-snippets/grpc-predictable-go-interfces/service" 8 | ) 9 | 10 | type Server struct { 11 | svc service.Service 12 | } 13 | 14 | func New(svc service.Service) *Server { 15 | return &Server{ 16 | svc: svc, 17 | } 18 | } 19 | 20 | func (s *Server) List(ctx context.Context, r *Request) (*Response, error) { 21 | entities, err := s.svc.List(int(r.Page), int(r.Limit)) 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | var out []*Entity 27 | 28 | for _, e := range entities { 29 | out = append(out, &Entity{Id: int32(e.ID), Name: e.Name}) 30 | } 31 | 32 | return &Response{Entities: out}, nil 33 | } 34 | 35 | func (s *Server) ListWithApplier(ctx context.Context, r *Request) (*Response, error) { 36 | entities, err := s.svc.ListWithApplier(paginator.FromRequest(r)) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | var out []*Entity 42 | 43 | for _, e := range entities { 44 | out = append(out, &Entity{Id: int32(e.ID), Name: e.Name}) 45 | } 46 | 47 | return &Response{Entities: out}, nil 48 | } 49 | 50 | func (s *Server) mustEmbedUnimplementedMyServiceServer() { 51 | panic("not implemented") // TODO: Implement 52 | } 53 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/transport/transport.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.10 5 | // source: transport.proto 6 | 7 | package transport 8 | 9 | import ( 10 | _ "google.golang.org/genproto/googleapis/api/annotations" 11 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 12 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type Request struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | Page int32 `protobuf:"varint,1,opt,name=page,proto3" json:"page,omitempty"` 30 | Limit int32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` 31 | Filter string `protobuf:"bytes,3,opt,name=filter,proto3" json:"filter,omitempty"` 32 | } 33 | 34 | func (x *Request) Reset() { 35 | *x = Request{} 36 | if protoimpl.UnsafeEnabled { 37 | mi := &file_transport_proto_msgTypes[0] 38 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 39 | ms.StoreMessageInfo(mi) 40 | } 41 | } 42 | 43 | func (x *Request) String() string { 44 | return protoimpl.X.MessageStringOf(x) 45 | } 46 | 47 | func (*Request) ProtoMessage() {} 48 | 49 | func (x *Request) ProtoReflect() protoreflect.Message { 50 | mi := &file_transport_proto_msgTypes[0] 51 | if protoimpl.UnsafeEnabled && x != nil { 52 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 53 | if ms.LoadMessageInfo() == nil { 54 | ms.StoreMessageInfo(mi) 55 | } 56 | return ms 57 | } 58 | return mi.MessageOf(x) 59 | } 60 | 61 | // Deprecated: Use Request.ProtoReflect.Descriptor instead. 62 | func (*Request) Descriptor() ([]byte, []int) { 63 | return file_transport_proto_rawDescGZIP(), []int{0} 64 | } 65 | 66 | func (x *Request) GetPage() int32 { 67 | if x != nil { 68 | return x.Page 69 | } 70 | return 0 71 | } 72 | 73 | func (x *Request) GetLimit() int32 { 74 | if x != nil { 75 | return x.Limit 76 | } 77 | return 0 78 | } 79 | 80 | func (x *Request) GetFilter() string { 81 | if x != nil { 82 | return x.Filter 83 | } 84 | return "" 85 | } 86 | 87 | type Response struct { 88 | state protoimpl.MessageState 89 | sizeCache protoimpl.SizeCache 90 | unknownFields protoimpl.UnknownFields 91 | 92 | Entities []*Entity `protobuf:"bytes,1,rep,name=entities,proto3" json:"entities,omitempty"` 93 | } 94 | 95 | func (x *Response) Reset() { 96 | *x = Response{} 97 | if protoimpl.UnsafeEnabled { 98 | mi := &file_transport_proto_msgTypes[1] 99 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 100 | ms.StoreMessageInfo(mi) 101 | } 102 | } 103 | 104 | func (x *Response) String() string { 105 | return protoimpl.X.MessageStringOf(x) 106 | } 107 | 108 | func (*Response) ProtoMessage() {} 109 | 110 | func (x *Response) ProtoReflect() protoreflect.Message { 111 | mi := &file_transport_proto_msgTypes[1] 112 | if protoimpl.UnsafeEnabled && x != nil { 113 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 114 | if ms.LoadMessageInfo() == nil { 115 | ms.StoreMessageInfo(mi) 116 | } 117 | return ms 118 | } 119 | return mi.MessageOf(x) 120 | } 121 | 122 | // Deprecated: Use Response.ProtoReflect.Descriptor instead. 123 | func (*Response) Descriptor() ([]byte, []int) { 124 | return file_transport_proto_rawDescGZIP(), []int{1} 125 | } 126 | 127 | func (x *Response) GetEntities() []*Entity { 128 | if x != nil { 129 | return x.Entities 130 | } 131 | return nil 132 | } 133 | 134 | type Entity struct { 135 | state protoimpl.MessageState 136 | sizeCache protoimpl.SizeCache 137 | unknownFields protoimpl.UnknownFields 138 | 139 | Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 140 | Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` 141 | } 142 | 143 | func (x *Entity) Reset() { 144 | *x = Entity{} 145 | if protoimpl.UnsafeEnabled { 146 | mi := &file_transport_proto_msgTypes[2] 147 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 148 | ms.StoreMessageInfo(mi) 149 | } 150 | } 151 | 152 | func (x *Entity) String() string { 153 | return protoimpl.X.MessageStringOf(x) 154 | } 155 | 156 | func (*Entity) ProtoMessage() {} 157 | 158 | func (x *Entity) ProtoReflect() protoreflect.Message { 159 | mi := &file_transport_proto_msgTypes[2] 160 | if protoimpl.UnsafeEnabled && x != nil { 161 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 162 | if ms.LoadMessageInfo() == nil { 163 | ms.StoreMessageInfo(mi) 164 | } 165 | return ms 166 | } 167 | return mi.MessageOf(x) 168 | } 169 | 170 | // Deprecated: Use Entity.ProtoReflect.Descriptor instead. 171 | func (*Entity) Descriptor() ([]byte, []int) { 172 | return file_transport_proto_rawDescGZIP(), []int{2} 173 | } 174 | 175 | func (x *Entity) GetId() int32 { 176 | if x != nil { 177 | return x.Id 178 | } 179 | return 0 180 | } 181 | 182 | func (x *Entity) GetName() string { 183 | if x != nil { 184 | return x.Name 185 | } 186 | return "" 187 | } 188 | 189 | var File_transport_proto protoreflect.FileDescriptor 190 | 191 | var file_transport_proto_rawDesc = []byte{ 192 | 0x0a, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 193 | 0x6f, 0x12, 0x03, 0x73, 0x76, 0x63, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 194 | 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 195 | 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4b, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 196 | 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 197 | 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 198 | 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 199 | 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 200 | 0x72, 0x22, 0x33, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 201 | 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 202 | 0x0b, 0x2e, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x65, 0x6e, 203 | 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x2c, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 204 | 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 205 | 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 206 | 0x6e, 0x61, 0x6d, 0x65, 0x32, 0x87, 0x01, 0x0a, 0x09, 0x4d, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 207 | 0x63, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x0c, 0x2e, 0x73, 0x76, 0x63, 208 | 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x73, 0x76, 0x63, 0x2e, 0x52, 209 | 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 210 | 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 211 | 0x74, 0x57, 0x69, 0x74, 0x68, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x12, 0x0c, 0x2e, 0x73, 212 | 0x76, 0x63, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x73, 0x76, 0x63, 213 | 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 214 | 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x77, 0x61, 0x42, 0x51, 215 | 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6b, 0x68, 216 | 0x61, 0x62, 0x61, 0x72, 0x6f, 0x76, 0x2f, 0x62, 0x6c, 0x6f, 0x67, 0x2d, 0x63, 0x6f, 0x64, 0x65, 217 | 0x2d, 0x73, 0x6e, 0x69, 0x70, 0x70, 0x65, 0x74, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x70, 218 | 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x67, 0x6f, 0x2d, 0x69, 0x6e, 219 | 0x74, 0x65, 0x72, 0x66, 0x63, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 220 | 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 221 | } 222 | 223 | var ( 224 | file_transport_proto_rawDescOnce sync.Once 225 | file_transport_proto_rawDescData = file_transport_proto_rawDesc 226 | ) 227 | 228 | func file_transport_proto_rawDescGZIP() []byte { 229 | file_transport_proto_rawDescOnce.Do(func() { 230 | file_transport_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_proto_rawDescData) 231 | }) 232 | return file_transport_proto_rawDescData 233 | } 234 | 235 | var file_transport_proto_msgTypes = make([]protoimpl.MessageInfo, 3) 236 | var file_transport_proto_goTypes = []interface{}{ 237 | (*Request)(nil), // 0: svc.Request 238 | (*Response)(nil), // 1: svc.Response 239 | (*Entity)(nil), // 2: svc.Entity 240 | } 241 | var file_transport_proto_depIdxs = []int32{ 242 | 2, // 0: svc.Response.entities:type_name -> svc.Entity 243 | 0, // 1: svc.MyService.List:input_type -> svc.Request 244 | 0, // 2: svc.MyService.ListWithApplier:input_type -> svc.Request 245 | 1, // 3: svc.MyService.List:output_type -> svc.Response 246 | 1, // 4: svc.MyService.ListWithApplier:output_type -> svc.Response 247 | 3, // [3:5] is the sub-list for method output_type 248 | 1, // [1:3] is the sub-list for method input_type 249 | 1, // [1:1] is the sub-list for extension type_name 250 | 1, // [1:1] is the sub-list for extension extendee 251 | 0, // [0:1] is the sub-list for field type_name 252 | } 253 | 254 | func init() { file_transport_proto_init() } 255 | func file_transport_proto_init() { 256 | if File_transport_proto != nil { 257 | return 258 | } 259 | if !protoimpl.UnsafeEnabled { 260 | file_transport_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 261 | switch v := v.(*Request); i { 262 | case 0: 263 | return &v.state 264 | case 1: 265 | return &v.sizeCache 266 | case 2: 267 | return &v.unknownFields 268 | default: 269 | return nil 270 | } 271 | } 272 | file_transport_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 273 | switch v := v.(*Response); i { 274 | case 0: 275 | return &v.state 276 | case 1: 277 | return &v.sizeCache 278 | case 2: 279 | return &v.unknownFields 280 | default: 281 | return nil 282 | } 283 | } 284 | file_transport_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 285 | switch v := v.(*Entity); i { 286 | case 0: 287 | return &v.state 288 | case 1: 289 | return &v.sizeCache 290 | case 2: 291 | return &v.unknownFields 292 | default: 293 | return nil 294 | } 295 | } 296 | } 297 | type x struct{} 298 | out := protoimpl.TypeBuilder{ 299 | File: protoimpl.DescBuilder{ 300 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 301 | RawDescriptor: file_transport_proto_rawDesc, 302 | NumEnums: 0, 303 | NumMessages: 3, 304 | NumExtensions: 0, 305 | NumServices: 1, 306 | }, 307 | GoTypes: file_transport_proto_goTypes, 308 | DependencyIndexes: file_transport_proto_depIdxs, 309 | MessageInfos: file_transport_proto_msgTypes, 310 | }.Build() 311 | File_transport_proto = out.File 312 | file_transport_proto_rawDesc = nil 313 | file_transport_proto_goTypes = nil 314 | file_transport_proto_depIdxs = nil 315 | } 316 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/transport/transport.pb.gw.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. 2 | // source: transport.proto 3 | 4 | /* 5 | Package transport is a reverse proxy. 6 | 7 | It translates gRPC into RESTful JSON APIs. 8 | */ 9 | package transport 10 | 11 | import ( 12 | "context" 13 | "io" 14 | "net/http" 15 | 16 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 17 | "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" 18 | "google.golang.org/grpc" 19 | "google.golang.org/grpc/codes" 20 | "google.golang.org/grpc/grpclog" 21 | "google.golang.org/grpc/metadata" 22 | "google.golang.org/grpc/status" 23 | "google.golang.org/protobuf/proto" 24 | ) 25 | 26 | // Suppress "imported and not used" errors 27 | var _ codes.Code 28 | var _ io.Reader 29 | var _ status.Status 30 | var _ = runtime.String 31 | var _ = utilities.NewDoubleArray 32 | var _ = metadata.Join 33 | 34 | var ( 35 | filter_MyService_List_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} 36 | ) 37 | 38 | func request_MyService_List_0(ctx context.Context, marshaler runtime.Marshaler, client MyServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 39 | var protoReq Request 40 | var metadata runtime.ServerMetadata 41 | 42 | if err := req.ParseForm(); err != nil { 43 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 44 | } 45 | if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_MyService_List_0); err != nil { 46 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 47 | } 48 | 49 | msg, err := client.List(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 50 | return msg, metadata, err 51 | 52 | } 53 | 54 | func local_request_MyService_List_0(ctx context.Context, marshaler runtime.Marshaler, server MyServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 55 | var protoReq Request 56 | var metadata runtime.ServerMetadata 57 | 58 | if err := req.ParseForm(); err != nil { 59 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 60 | } 61 | if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_MyService_List_0); err != nil { 62 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 63 | } 64 | 65 | msg, err := server.List(ctx, &protoReq) 66 | return msg, metadata, err 67 | 68 | } 69 | 70 | var ( 71 | filter_MyService_ListWithApplier_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} 72 | ) 73 | 74 | func request_MyService_ListWithApplier_0(ctx context.Context, marshaler runtime.Marshaler, client MyServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 75 | var protoReq Request 76 | var metadata runtime.ServerMetadata 77 | 78 | if err := req.ParseForm(); err != nil { 79 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 80 | } 81 | if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_MyService_ListWithApplier_0); err != nil { 82 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 83 | } 84 | 85 | msg, err := client.ListWithApplier(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 86 | return msg, metadata, err 87 | 88 | } 89 | 90 | func local_request_MyService_ListWithApplier_0(ctx context.Context, marshaler runtime.Marshaler, server MyServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 91 | var protoReq Request 92 | var metadata runtime.ServerMetadata 93 | 94 | if err := req.ParseForm(); err != nil { 95 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 96 | } 97 | if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_MyService_ListWithApplier_0); err != nil { 98 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 99 | } 100 | 101 | msg, err := server.ListWithApplier(ctx, &protoReq) 102 | return msg, metadata, err 103 | 104 | } 105 | 106 | // RegisterMyServiceHandlerServer registers the http handlers for service MyService to "mux". 107 | // UnaryRPC :call MyServiceServer directly. 108 | // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. 109 | // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterMyServiceHandlerFromEndpoint instead. 110 | func RegisterMyServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server MyServiceServer) error { 111 | 112 | mux.Handle("GET", pattern_MyService_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 113 | ctx, cancel := context.WithCancel(req.Context()) 114 | defer cancel() 115 | var stream runtime.ServerTransportStream 116 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 117 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 118 | var err error 119 | var annotatedContext context.Context 120 | annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/svc.MyService/List", runtime.WithHTTPPathPattern("/v1/list")) 121 | if err != nil { 122 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 123 | return 124 | } 125 | resp, md, err := local_request_MyService_List_0(annotatedContext, inboundMarshaler, server, req, pathParams) 126 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 127 | annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) 128 | if err != nil { 129 | runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) 130 | return 131 | } 132 | 133 | forward_MyService_List_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 134 | 135 | }) 136 | 137 | mux.Handle("GET", pattern_MyService_ListWithApplier_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 138 | ctx, cancel := context.WithCancel(req.Context()) 139 | defer cancel() 140 | var stream runtime.ServerTransportStream 141 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 142 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 143 | var err error 144 | var annotatedContext context.Context 145 | annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/svc.MyService/ListWithApplier", runtime.WithHTTPPathPattern("/v1/list-wa")) 146 | if err != nil { 147 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 148 | return 149 | } 150 | resp, md, err := local_request_MyService_ListWithApplier_0(annotatedContext, inboundMarshaler, server, req, pathParams) 151 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 152 | annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) 153 | if err != nil { 154 | runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) 155 | return 156 | } 157 | 158 | forward_MyService_ListWithApplier_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 159 | 160 | }) 161 | 162 | return nil 163 | } 164 | 165 | // RegisterMyServiceHandlerFromEndpoint is same as RegisterMyServiceHandler but 166 | // automatically dials to "endpoint" and closes the connection when "ctx" gets done. 167 | func RegisterMyServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { 168 | conn, err := grpc.Dial(endpoint, opts...) 169 | if err != nil { 170 | return err 171 | } 172 | defer func() { 173 | if err != nil { 174 | if cerr := conn.Close(); cerr != nil { 175 | grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) 176 | } 177 | return 178 | } 179 | go func() { 180 | <-ctx.Done() 181 | if cerr := conn.Close(); cerr != nil { 182 | grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) 183 | } 184 | }() 185 | }() 186 | 187 | return RegisterMyServiceHandler(ctx, mux, conn) 188 | } 189 | 190 | // RegisterMyServiceHandler registers the http handlers for service MyService to "mux". 191 | // The handlers forward requests to the grpc endpoint over "conn". 192 | func RegisterMyServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { 193 | return RegisterMyServiceHandlerClient(ctx, mux, NewMyServiceClient(conn)) 194 | } 195 | 196 | // RegisterMyServiceHandlerClient registers the http handlers for service MyService 197 | // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "MyServiceClient". 198 | // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "MyServiceClient" 199 | // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in 200 | // "MyServiceClient" to call the correct interceptors. 201 | func RegisterMyServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client MyServiceClient) error { 202 | 203 | mux.Handle("GET", pattern_MyService_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 204 | ctx, cancel := context.WithCancel(req.Context()) 205 | defer cancel() 206 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 207 | var err error 208 | var annotatedContext context.Context 209 | annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/svc.MyService/List", runtime.WithHTTPPathPattern("/v1/list")) 210 | if err != nil { 211 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 212 | return 213 | } 214 | resp, md, err := request_MyService_List_0(annotatedContext, inboundMarshaler, client, req, pathParams) 215 | annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) 216 | if err != nil { 217 | runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) 218 | return 219 | } 220 | 221 | forward_MyService_List_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 222 | 223 | }) 224 | 225 | mux.Handle("GET", pattern_MyService_ListWithApplier_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 226 | ctx, cancel := context.WithCancel(req.Context()) 227 | defer cancel() 228 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 229 | var err error 230 | var annotatedContext context.Context 231 | annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/svc.MyService/ListWithApplier", runtime.WithHTTPPathPattern("/v1/list-wa")) 232 | if err != nil { 233 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 234 | return 235 | } 236 | resp, md, err := request_MyService_ListWithApplier_0(annotatedContext, inboundMarshaler, client, req, pathParams) 237 | annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) 238 | if err != nil { 239 | runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) 240 | return 241 | } 242 | 243 | forward_MyService_ListWithApplier_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 244 | 245 | }) 246 | 247 | return nil 248 | } 249 | 250 | var ( 251 | pattern_MyService_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "list"}, "")) 252 | 253 | pattern_MyService_ListWithApplier_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "list-wa"}, "")) 254 | ) 255 | 256 | var ( 257 | forward_MyService_List_0 = runtime.ForwardResponseMessage 258 | 259 | forward_MyService_ListWithApplier_0 = runtime.ForwardResponseMessage 260 | ) 261 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/transport/transport.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package svc; 4 | 5 | option go_package = "github.com/ekhabarov/blog-code-snippets/grpc-predictable-go-interfces/transport"; 6 | 7 | import "google/api/annotations.proto"; 8 | 9 | service MyService { 10 | rpc List(Request) returns (Response) { 11 | option (google.api.http) = { get: "/v1/list" }; 12 | } 13 | 14 | rpc ListWithApplier(Request) returns (Response) { 15 | option (google.api.http) = { get: "/v1/list-wa" }; 16 | } 17 | } 18 | 19 | message Request { 20 | int32 page = 1; 21 | int32 limit = 2; 22 | string filter = 3; 23 | } 24 | 25 | message Response { 26 | repeated Entity entities = 1; 27 | } 28 | 29 | message Entity { 30 | int32 id = 1; 31 | string name = 2; 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /grpc-predictable-go-interfaces/transport/transport_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.10 5 | // source: transport.proto 6 | 7 | package transport 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 | // MyServiceClient is the client API for MyService 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 MyServiceClient interface { 25 | List(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) 26 | ListWithApplier(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) 27 | } 28 | 29 | type myServiceClient struct { 30 | cc grpc.ClientConnInterface 31 | } 32 | 33 | func NewMyServiceClient(cc grpc.ClientConnInterface) MyServiceClient { 34 | return &myServiceClient{cc} 35 | } 36 | 37 | func (c *myServiceClient) List(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { 38 | out := new(Response) 39 | err := c.cc.Invoke(ctx, "/svc.MyService/List", in, out, opts...) 40 | if err != nil { 41 | return nil, err 42 | } 43 | return out, nil 44 | } 45 | 46 | func (c *myServiceClient) ListWithApplier(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { 47 | out := new(Response) 48 | err := c.cc.Invoke(ctx, "/svc.MyService/ListWithApplier", in, out, opts...) 49 | if err != nil { 50 | return nil, err 51 | } 52 | return out, nil 53 | } 54 | 55 | // MyServiceServer is the server API for MyService service. 56 | // All implementations must embed UnimplementedMyServiceServer 57 | // for forward compatibility 58 | type MyServiceServer interface { 59 | List(context.Context, *Request) (*Response, error) 60 | ListWithApplier(context.Context, *Request) (*Response, error) 61 | mustEmbedUnimplementedMyServiceServer() 62 | } 63 | 64 | // UnimplementedMyServiceServer must be embedded to have forward compatible implementations. 65 | type UnimplementedMyServiceServer struct { 66 | } 67 | 68 | func (UnimplementedMyServiceServer) List(context.Context, *Request) (*Response, error) { 69 | return nil, status.Errorf(codes.Unimplemented, "method List not implemented") 70 | } 71 | func (UnimplementedMyServiceServer) ListWithApplier(context.Context, *Request) (*Response, error) { 72 | return nil, status.Errorf(codes.Unimplemented, "method ListWithApplier not implemented") 73 | } 74 | func (UnimplementedMyServiceServer) mustEmbedUnimplementedMyServiceServer() {} 75 | 76 | // UnsafeMyServiceServer may be embedded to opt out of forward compatibility for this service. 77 | // Use of this interface is not recommended, as added methods to MyServiceServer will 78 | // result in compilation errors. 79 | type UnsafeMyServiceServer interface { 80 | mustEmbedUnimplementedMyServiceServer() 81 | } 82 | 83 | func RegisterMyServiceServer(s grpc.ServiceRegistrar, srv MyServiceServer) { 84 | s.RegisterService(&MyService_ServiceDesc, srv) 85 | } 86 | 87 | func _MyService_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 88 | in := new(Request) 89 | if err := dec(in); err != nil { 90 | return nil, err 91 | } 92 | if interceptor == nil { 93 | return srv.(MyServiceServer).List(ctx, in) 94 | } 95 | info := &grpc.UnaryServerInfo{ 96 | Server: srv, 97 | FullMethod: "/svc.MyService/List", 98 | } 99 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 100 | return srv.(MyServiceServer).List(ctx, req.(*Request)) 101 | } 102 | return interceptor(ctx, in, info, handler) 103 | } 104 | 105 | func _MyService_ListWithApplier_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 106 | in := new(Request) 107 | if err := dec(in); err != nil { 108 | return nil, err 109 | } 110 | if interceptor == nil { 111 | return srv.(MyServiceServer).ListWithApplier(ctx, in) 112 | } 113 | info := &grpc.UnaryServerInfo{ 114 | Server: srv, 115 | FullMethod: "/svc.MyService/ListWithApplier", 116 | } 117 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 118 | return srv.(MyServiceServer).ListWithApplier(ctx, req.(*Request)) 119 | } 120 | return interceptor(ctx, in, info, handler) 121 | } 122 | 123 | // MyService_ServiceDesc is the grpc.ServiceDesc for MyService service. 124 | // It's only intended for direct use with grpc.RegisterService, 125 | // and not to be introspected or modified (even as a copy) 126 | var MyService_ServiceDesc = grpc.ServiceDesc{ 127 | ServiceName: "svc.MyService", 128 | HandlerType: (*MyServiceServer)(nil), 129 | Methods: []grpc.MethodDesc{ 130 | { 131 | MethodName: "List", 132 | Handler: _MyService_List_Handler, 133 | }, 134 | { 135 | MethodName: "ListWithApplier", 136 | Handler: _MyService_ListWithApplier_Handler, 137 | }, 138 | }, 139 | Streams: []grpc.StreamDesc{}, 140 | Metadata: "transport.proto", 141 | } 142 | -------------------------------------------------------------------------------- /grpc-with-business-logic/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | "github.com/ekhabarov/blog-code-snippets/grpc-with-business-logic/pb" 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | func main() { 14 | cc, err := grpc.Dial("127.0.0.1:5001", grpc.WithInsecure()) 15 | if err != nil { 16 | log.Fatal(err) 17 | } 18 | defer cc.Close() 19 | 20 | client := pb.NewOrderServiceClient(cc) 21 | 22 | r, err := client.Get(context.Background(), &pb.GetRequest{Id: 2}) 23 | if err != nil { 24 | log.Fatal(err) 25 | } 26 | 27 | fmt.Printf("order:\nID: %d, Number: %s, Status: %s\n", r.Order.Id, r.Order.Number, r.Order.Status) 28 | 29 | for _, i := range r.Order.Items { 30 | fmt.Printf("\titem: ID: %d, Name: %s, Qty: %d\n", i.Id, i.Name, i.Qty) 31 | } 32 | 33 | newOrder, err := client.Add(context.Background(), &pb.AddRequest{ 34 | Body: &pb.AddRequest_Body{ 35 | Order: &pb.Order{ 36 | Id: 1, 37 | Number: "123", 38 | Status: "new", 39 | CreatedAt: time.Now().Unix(), 40 | }, 41 | }, 42 | }) 43 | if err != nil { 44 | log.Fatal(err) 45 | } 46 | 47 | fmt.Printf("\nnew order ID: %d, Status: %s\n", newOrder.Id, newOrder.Status) 48 | } 49 | -------------------------------------------------------------------------------- /grpc-with-business-logic/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ekhabarov/blog-code-snippets/grpc-with-business-logic 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/golang/protobuf v1.3.2 7 | google.golang.org/grpc v1.26.0 8 | ) 9 | -------------------------------------------------------------------------------- /grpc-with-business-logic/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/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 6 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 7 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 8 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 9 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 10 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 11 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 12 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 13 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 14 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 15 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 16 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 17 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 18 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 19 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 20 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 21 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 22 | golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= 23 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 24 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 25 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 26 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 27 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 28 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 29 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 30 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 31 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 32 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 33 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 34 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 35 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 36 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 37 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 38 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 39 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= 40 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 41 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 42 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 43 | google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= 44 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 45 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 46 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 47 | -------------------------------------------------------------------------------- /grpc-with-business-logic/pb/order.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: pb/order.proto 3 | 4 | package pb 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | type Item struct { 28 | Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 29 | Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` 30 | Qty int32 `protobuf:"varint,3,opt,name=qty,proto3" json:"qty,omitempty"` 31 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 32 | XXX_unrecognized []byte `json:"-"` 33 | XXX_sizecache int32 `json:"-"` 34 | } 35 | 36 | func (m *Item) Reset() { *m = Item{} } 37 | func (m *Item) String() string { return proto.CompactTextString(m) } 38 | func (*Item) ProtoMessage() {} 39 | func (*Item) Descriptor() ([]byte, []int) { 40 | return fileDescriptor_e4944acb1d14eb6b, []int{0} 41 | } 42 | 43 | func (m *Item) XXX_Unmarshal(b []byte) error { 44 | return xxx_messageInfo_Item.Unmarshal(m, b) 45 | } 46 | func (m *Item) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 47 | return xxx_messageInfo_Item.Marshal(b, m, deterministic) 48 | } 49 | func (m *Item) XXX_Merge(src proto.Message) { 50 | xxx_messageInfo_Item.Merge(m, src) 51 | } 52 | func (m *Item) XXX_Size() int { 53 | return xxx_messageInfo_Item.Size(m) 54 | } 55 | func (m *Item) XXX_DiscardUnknown() { 56 | xxx_messageInfo_Item.DiscardUnknown(m) 57 | } 58 | 59 | var xxx_messageInfo_Item proto.InternalMessageInfo 60 | 61 | func (m *Item) GetId() int64 { 62 | if m != nil { 63 | return m.Id 64 | } 65 | return 0 66 | } 67 | 68 | func (m *Item) GetName() string { 69 | if m != nil { 70 | return m.Name 71 | } 72 | return "" 73 | } 74 | 75 | func (m *Item) GetQty() int32 { 76 | if m != nil { 77 | return m.Qty 78 | } 79 | return 0 80 | } 81 | 82 | type Order struct { 83 | Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 84 | Number string `protobuf:"bytes,2,opt,name=number,proto3" json:"number,omitempty"` 85 | Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` 86 | CreatedAt int64 `protobuf:"varint,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` 87 | Items []*Item `protobuf:"bytes,5,rep,name=items,proto3" json:"items,omitempty"` 88 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 89 | XXX_unrecognized []byte `json:"-"` 90 | XXX_sizecache int32 `json:"-"` 91 | } 92 | 93 | func (m *Order) Reset() { *m = Order{} } 94 | func (m *Order) String() string { return proto.CompactTextString(m) } 95 | func (*Order) ProtoMessage() {} 96 | func (*Order) Descriptor() ([]byte, []int) { 97 | return fileDescriptor_e4944acb1d14eb6b, []int{1} 98 | } 99 | 100 | func (m *Order) XXX_Unmarshal(b []byte) error { 101 | return xxx_messageInfo_Order.Unmarshal(m, b) 102 | } 103 | func (m *Order) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 104 | return xxx_messageInfo_Order.Marshal(b, m, deterministic) 105 | } 106 | func (m *Order) XXX_Merge(src proto.Message) { 107 | xxx_messageInfo_Order.Merge(m, src) 108 | } 109 | func (m *Order) XXX_Size() int { 110 | return xxx_messageInfo_Order.Size(m) 111 | } 112 | func (m *Order) XXX_DiscardUnknown() { 113 | xxx_messageInfo_Order.DiscardUnknown(m) 114 | } 115 | 116 | var xxx_messageInfo_Order proto.InternalMessageInfo 117 | 118 | func (m *Order) GetId() int64 { 119 | if m != nil { 120 | return m.Id 121 | } 122 | return 0 123 | } 124 | 125 | func (m *Order) GetNumber() string { 126 | if m != nil { 127 | return m.Number 128 | } 129 | return "" 130 | } 131 | 132 | func (m *Order) GetStatus() string { 133 | if m != nil { 134 | return m.Status 135 | } 136 | return "" 137 | } 138 | 139 | func (m *Order) GetCreatedAt() int64 { 140 | if m != nil { 141 | return m.CreatedAt 142 | } 143 | return 0 144 | } 145 | 146 | func (m *Order) GetItems() []*Item { 147 | if m != nil { 148 | return m.Items 149 | } 150 | return nil 151 | } 152 | 153 | type GetRequest struct { 154 | Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 155 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 156 | XXX_unrecognized []byte `json:"-"` 157 | XXX_sizecache int32 `json:"-"` 158 | } 159 | 160 | func (m *GetRequest) Reset() { *m = GetRequest{} } 161 | func (m *GetRequest) String() string { return proto.CompactTextString(m) } 162 | func (*GetRequest) ProtoMessage() {} 163 | func (*GetRequest) Descriptor() ([]byte, []int) { 164 | return fileDescriptor_e4944acb1d14eb6b, []int{2} 165 | } 166 | 167 | func (m *GetRequest) XXX_Unmarshal(b []byte) error { 168 | return xxx_messageInfo_GetRequest.Unmarshal(m, b) 169 | } 170 | func (m *GetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 171 | return xxx_messageInfo_GetRequest.Marshal(b, m, deterministic) 172 | } 173 | func (m *GetRequest) XXX_Merge(src proto.Message) { 174 | xxx_messageInfo_GetRequest.Merge(m, src) 175 | } 176 | func (m *GetRequest) XXX_Size() int { 177 | return xxx_messageInfo_GetRequest.Size(m) 178 | } 179 | func (m *GetRequest) XXX_DiscardUnknown() { 180 | xxx_messageInfo_GetRequest.DiscardUnknown(m) 181 | } 182 | 183 | var xxx_messageInfo_GetRequest proto.InternalMessageInfo 184 | 185 | func (m *GetRequest) GetId() int64 { 186 | if m != nil { 187 | return m.Id 188 | } 189 | return 0 190 | } 191 | 192 | type GetResponse struct { 193 | Order *Order `protobuf:"bytes,1,opt,name=order,proto3" json:"order,omitempty"` 194 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 195 | XXX_unrecognized []byte `json:"-"` 196 | XXX_sizecache int32 `json:"-"` 197 | } 198 | 199 | func (m *GetResponse) Reset() { *m = GetResponse{} } 200 | func (m *GetResponse) String() string { return proto.CompactTextString(m) } 201 | func (*GetResponse) ProtoMessage() {} 202 | func (*GetResponse) Descriptor() ([]byte, []int) { 203 | return fileDescriptor_e4944acb1d14eb6b, []int{3} 204 | } 205 | 206 | func (m *GetResponse) XXX_Unmarshal(b []byte) error { 207 | return xxx_messageInfo_GetResponse.Unmarshal(m, b) 208 | } 209 | func (m *GetResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 210 | return xxx_messageInfo_GetResponse.Marshal(b, m, deterministic) 211 | } 212 | func (m *GetResponse) XXX_Merge(src proto.Message) { 213 | xxx_messageInfo_GetResponse.Merge(m, src) 214 | } 215 | func (m *GetResponse) XXX_Size() int { 216 | return xxx_messageInfo_GetResponse.Size(m) 217 | } 218 | func (m *GetResponse) XXX_DiscardUnknown() { 219 | xxx_messageInfo_GetResponse.DiscardUnknown(m) 220 | } 221 | 222 | var xxx_messageInfo_GetResponse proto.InternalMessageInfo 223 | 224 | func (m *GetResponse) GetOrder() *Order { 225 | if m != nil { 226 | return m.Order 227 | } 228 | return nil 229 | } 230 | 231 | type AddRequest struct { 232 | Body *AddRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` 233 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 234 | XXX_unrecognized []byte `json:"-"` 235 | XXX_sizecache int32 `json:"-"` 236 | } 237 | 238 | func (m *AddRequest) Reset() { *m = AddRequest{} } 239 | func (m *AddRequest) String() string { return proto.CompactTextString(m) } 240 | func (*AddRequest) ProtoMessage() {} 241 | func (*AddRequest) Descriptor() ([]byte, []int) { 242 | return fileDescriptor_e4944acb1d14eb6b, []int{4} 243 | } 244 | 245 | func (m *AddRequest) XXX_Unmarshal(b []byte) error { 246 | return xxx_messageInfo_AddRequest.Unmarshal(m, b) 247 | } 248 | func (m *AddRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 249 | return xxx_messageInfo_AddRequest.Marshal(b, m, deterministic) 250 | } 251 | func (m *AddRequest) XXX_Merge(src proto.Message) { 252 | xxx_messageInfo_AddRequest.Merge(m, src) 253 | } 254 | func (m *AddRequest) XXX_Size() int { 255 | return xxx_messageInfo_AddRequest.Size(m) 256 | } 257 | func (m *AddRequest) XXX_DiscardUnknown() { 258 | xxx_messageInfo_AddRequest.DiscardUnknown(m) 259 | } 260 | 261 | var xxx_messageInfo_AddRequest proto.InternalMessageInfo 262 | 263 | func (m *AddRequest) GetBody() *AddRequest_Body { 264 | if m != nil { 265 | return m.Body 266 | } 267 | return nil 268 | } 269 | 270 | type AddRequest_Body struct { 271 | Order *Order `protobuf:"bytes,1,opt,name=order,proto3" json:"order,omitempty"` 272 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 273 | XXX_unrecognized []byte `json:"-"` 274 | XXX_sizecache int32 `json:"-"` 275 | } 276 | 277 | func (m *AddRequest_Body) Reset() { *m = AddRequest_Body{} } 278 | func (m *AddRequest_Body) String() string { return proto.CompactTextString(m) } 279 | func (*AddRequest_Body) ProtoMessage() {} 280 | func (*AddRequest_Body) Descriptor() ([]byte, []int) { 281 | return fileDescriptor_e4944acb1d14eb6b, []int{4, 0} 282 | } 283 | 284 | func (m *AddRequest_Body) XXX_Unmarshal(b []byte) error { 285 | return xxx_messageInfo_AddRequest_Body.Unmarshal(m, b) 286 | } 287 | func (m *AddRequest_Body) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 288 | return xxx_messageInfo_AddRequest_Body.Marshal(b, m, deterministic) 289 | } 290 | func (m *AddRequest_Body) XXX_Merge(src proto.Message) { 291 | xxx_messageInfo_AddRequest_Body.Merge(m, src) 292 | } 293 | func (m *AddRequest_Body) XXX_Size() int { 294 | return xxx_messageInfo_AddRequest_Body.Size(m) 295 | } 296 | func (m *AddRequest_Body) XXX_DiscardUnknown() { 297 | xxx_messageInfo_AddRequest_Body.DiscardUnknown(m) 298 | } 299 | 300 | var xxx_messageInfo_AddRequest_Body proto.InternalMessageInfo 301 | 302 | func (m *AddRequest_Body) GetOrder() *Order { 303 | if m != nil { 304 | return m.Order 305 | } 306 | return nil 307 | } 308 | 309 | type AddResponse struct { 310 | Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 311 | Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` 312 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 313 | XXX_unrecognized []byte `json:"-"` 314 | XXX_sizecache int32 `json:"-"` 315 | } 316 | 317 | func (m *AddResponse) Reset() { *m = AddResponse{} } 318 | func (m *AddResponse) String() string { return proto.CompactTextString(m) } 319 | func (*AddResponse) ProtoMessage() {} 320 | func (*AddResponse) Descriptor() ([]byte, []int) { 321 | return fileDescriptor_e4944acb1d14eb6b, []int{5} 322 | } 323 | 324 | func (m *AddResponse) XXX_Unmarshal(b []byte) error { 325 | return xxx_messageInfo_AddResponse.Unmarshal(m, b) 326 | } 327 | func (m *AddResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 328 | return xxx_messageInfo_AddResponse.Marshal(b, m, deterministic) 329 | } 330 | func (m *AddResponse) XXX_Merge(src proto.Message) { 331 | xxx_messageInfo_AddResponse.Merge(m, src) 332 | } 333 | func (m *AddResponse) XXX_Size() int { 334 | return xxx_messageInfo_AddResponse.Size(m) 335 | } 336 | func (m *AddResponse) XXX_DiscardUnknown() { 337 | xxx_messageInfo_AddResponse.DiscardUnknown(m) 338 | } 339 | 340 | var xxx_messageInfo_AddResponse proto.InternalMessageInfo 341 | 342 | func (m *AddResponse) GetId() int64 { 343 | if m != nil { 344 | return m.Id 345 | } 346 | return 0 347 | } 348 | 349 | func (m *AddResponse) GetStatus() string { 350 | if m != nil { 351 | return m.Status 352 | } 353 | return "" 354 | } 355 | 356 | func init() { 357 | proto.RegisterType((*Item)(nil), "Item") 358 | proto.RegisterType((*Order)(nil), "Order") 359 | proto.RegisterType((*GetRequest)(nil), "GetRequest") 360 | proto.RegisterType((*GetResponse)(nil), "GetResponse") 361 | proto.RegisterType((*AddRequest)(nil), "AddRequest") 362 | proto.RegisterType((*AddRequest_Body)(nil), "AddRequest.Body") 363 | proto.RegisterType((*AddResponse)(nil), "AddResponse") 364 | } 365 | 366 | func init() { proto.RegisterFile("pb/order.proto", fileDescriptor_e4944acb1d14eb6b) } 367 | 368 | var fileDescriptor_e4944acb1d14eb6b = []byte{ 369 | // 314 bytes of a gzipped FileDescriptorProto 370 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0x3f, 0x6b, 0xc3, 0x30, 371 | 0x10, 0xc5, 0xf1, 0xbf, 0x40, 0x4e, 0x21, 0x04, 0x0d, 0xc5, 0xa4, 0x29, 0x08, 0x93, 0xc1, 0x50, 372 | 0x50, 0x21, 0xa5, 0x5b, 0x97, 0x64, 0x09, 0x9d, 0x0a, 0xea, 0x52, 0xba, 0x14, 0x3b, 0xba, 0xc1, 373 | 0x83, 0x23, 0x47, 0xba, 0x14, 0x32, 0xf7, 0x8b, 0x17, 0x2b, 0x2a, 0x31, 0x6d, 0xa1, 0xdb, 0xdd, 374 | 0xbb, 0xbb, 0x9f, 0xde, 0x1d, 0x82, 0x69, 0x57, 0xdf, 0x19, 0xab, 0xd1, 0xca, 0xce, 0x1a, 0x32, 375 | 0xc5, 0x23, 0xa4, 0x4f, 0x84, 0x2d, 0x9f, 0x42, 0xdc, 0xe8, 0x3c, 0x12, 0x51, 0x99, 0xa8, 0xb8, 376 | 0xd1, 0x9c, 0x43, 0xba, 0xaf, 0x5a, 0xcc, 0x63, 0x11, 0x95, 0x63, 0xe5, 0x63, 0x3e, 0x83, 0xe4, 377 | 0x40, 0xa7, 0x3c, 0x11, 0x51, 0x99, 0xa9, 0x3e, 0x2c, 0x3e, 0x23, 0xc8, 0x9e, 0x7b, 0xda, 0xaf, 378 | 0xf9, 0x2b, 0x18, 0xed, 0x8f, 0x6d, 0x8d, 0x36, 0x10, 0x42, 0xd6, 0xeb, 0x8e, 0x2a, 0x3a, 0x3a, 379 | 0x8f, 0x19, 0xab, 0x90, 0xf1, 0x1b, 0x80, 0x9d, 0xc5, 0x8a, 0x50, 0xbf, 0x57, 0x94, 0xa7, 0x9e, 380 | 0x33, 0x0e, 0xca, 0x9a, 0xf8, 0x35, 0x64, 0x0d, 0x61, 0xeb, 0xf2, 0x4c, 0x24, 0x25, 0x5b, 0x65, 381 | 0xb2, 0x37, 0xad, 0xce, 0x5a, 0xb1, 0x00, 0xd8, 0x22, 0x29, 0x3c, 0x1c, 0xd1, 0xd1, 0x4f, 0x27, 382 | 0xc5, 0x2d, 0x30, 0x5f, 0x75, 0x9d, 0xd9, 0x3b, 0xe4, 0x0b, 0xc8, 0xfc, 0xfe, 0xbe, 0x83, 0xad, 383 | 0x46, 0xd2, 0xfb, 0x57, 0x67, 0xb1, 0x78, 0x05, 0x58, 0x6b, 0xfd, 0x8d, 0x5a, 0x42, 0x5a, 0x1b, 384 | 0x7d, 0x0a, 0xad, 0x33, 0x79, 0x29, 0xc9, 0x8d, 0xd1, 0x27, 0xe5, 0xab, 0xf3, 0x25, 0xa4, 0x7d, 385 | 0xf6, 0x0f, 0xf9, 0x01, 0x98, 0x1f, 0x0f, 0x36, 0xfe, 0xb8, 0x57, 0xb8, 0x4b, 0x3c, 0xbc, 0xcb, 386 | 0x4a, 0xc1, 0xc4, 0x63, 0x5e, 0xd0, 0x7e, 0x34, 0x3b, 0xe4, 0x02, 0x92, 0x2d, 0x12, 0x67, 0xf2, 387 | 0xb2, 0xf1, 0x7c, 0x22, 0x87, 0x0b, 0x0a, 0x48, 0xd6, 0x5a, 0x73, 0x36, 0x70, 0x3b, 0x9f, 0xc8, 388 | 0xc1, 0xdb, 0x9b, 0xf4, 0x2d, 0xee, 0xea, 0x7a, 0xe4, 0x3f, 0xc0, 0xfd, 0x57, 0x00, 0x00, 0x00, 389 | 0xff, 0xff, 0xc4, 0x0d, 0x1a, 0xc7, 0x12, 0x02, 0x00, 0x00, 390 | } 391 | 392 | // Reference imports to suppress errors if they are not otherwise used. 393 | var _ context.Context 394 | var _ grpc.ClientConn 395 | 396 | // This is a compile-time assertion to ensure that this generated file 397 | // is compatible with the grpc package it is being compiled against. 398 | const _ = grpc.SupportPackageIsVersion4 399 | 400 | // OrderServiceClient is the client API for OrderService service. 401 | // 402 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 403 | type OrderServiceClient interface { 404 | Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) 405 | Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) 406 | } 407 | 408 | type orderServiceClient struct { 409 | cc *grpc.ClientConn 410 | } 411 | 412 | func NewOrderServiceClient(cc *grpc.ClientConn) OrderServiceClient { 413 | return &orderServiceClient{cc} 414 | } 415 | 416 | func (c *orderServiceClient) Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) { 417 | out := new(GetResponse) 418 | err := c.cc.Invoke(ctx, "/OrderService/Get", in, out, opts...) 419 | if err != nil { 420 | return nil, err 421 | } 422 | return out, nil 423 | } 424 | 425 | func (c *orderServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) { 426 | out := new(AddResponse) 427 | err := c.cc.Invoke(ctx, "/OrderService/Add", in, out, opts...) 428 | if err != nil { 429 | return nil, err 430 | } 431 | return out, nil 432 | } 433 | 434 | // OrderServiceServer is the server API for OrderService service. 435 | type OrderServiceServer interface { 436 | Get(context.Context, *GetRequest) (*GetResponse, error) 437 | Add(context.Context, *AddRequest) (*AddResponse, error) 438 | } 439 | 440 | // UnimplementedOrderServiceServer can be embedded to have forward compatible implementations. 441 | type UnimplementedOrderServiceServer struct { 442 | } 443 | 444 | func (*UnimplementedOrderServiceServer) Get(ctx context.Context, req *GetRequest) (*GetResponse, error) { 445 | return nil, status.Errorf(codes.Unimplemented, "method Get not implemented") 446 | } 447 | func (*UnimplementedOrderServiceServer) Add(ctx context.Context, req *AddRequest) (*AddResponse, error) { 448 | return nil, status.Errorf(codes.Unimplemented, "method Add not implemented") 449 | } 450 | 451 | func RegisterOrderServiceServer(s *grpc.Server, srv OrderServiceServer) { 452 | s.RegisterService(&_OrderService_serviceDesc, srv) 453 | } 454 | 455 | func _OrderService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 456 | in := new(GetRequest) 457 | if err := dec(in); err != nil { 458 | return nil, err 459 | } 460 | if interceptor == nil { 461 | return srv.(OrderServiceServer).Get(ctx, in) 462 | } 463 | info := &grpc.UnaryServerInfo{ 464 | Server: srv, 465 | FullMethod: "/OrderService/Get", 466 | } 467 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 468 | return srv.(OrderServiceServer).Get(ctx, req.(*GetRequest)) 469 | } 470 | return interceptor(ctx, in, info, handler) 471 | } 472 | 473 | func _OrderService_Add_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 474 | in := new(AddRequest) 475 | if err := dec(in); err != nil { 476 | return nil, err 477 | } 478 | if interceptor == nil { 479 | return srv.(OrderServiceServer).Add(ctx, in) 480 | } 481 | info := &grpc.UnaryServerInfo{ 482 | Server: srv, 483 | FullMethod: "/OrderService/Add", 484 | } 485 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 486 | return srv.(OrderServiceServer).Add(ctx, req.(*AddRequest)) 487 | } 488 | return interceptor(ctx, in, info, handler) 489 | } 490 | 491 | var _OrderService_serviceDesc = grpc.ServiceDesc{ 492 | ServiceName: "OrderService", 493 | HandlerType: (*OrderServiceServer)(nil), 494 | Methods: []grpc.MethodDesc{ 495 | { 496 | MethodName: "Get", 497 | Handler: _OrderService_Get_Handler, 498 | }, 499 | { 500 | MethodName: "Add", 501 | Handler: _OrderService_Add_Handler, 502 | }, 503 | }, 504 | Streams: []grpc.StreamDesc{}, 505 | Metadata: "pb/order.proto", 506 | } 507 | -------------------------------------------------------------------------------- /grpc-with-business-logic/pb/order.proto: -------------------------------------------------------------------------------- 1 | // Generate Golang code with 2 | // protoc --go_out=plugins=grpc:. ./order.proto 3 | 4 | syntax = "proto3"; 5 | option go_package = "pb"; 6 | 7 | service OrderService { 8 | rpc Get(GetRequest) returns (GetResponse); 9 | rpc Add(AddRequest) returns (AddResponse); 10 | } 11 | 12 | message Item { 13 | int64 id = 1; 14 | string name = 2; 15 | int32 qty = 3; 16 | } 17 | 18 | message Order { 19 | int64 id = 1; 20 | string number = 2; 21 | string status = 3; 22 | int64 created_at = 4; 23 | repeated Item items = 5; 24 | } 25 | 26 | message GetRequest { 27 | int64 id = 1; 28 | } 29 | 30 | message GetResponse { 31 | Order order = 1; 32 | } 33 | 34 | message AddRequest { 35 | message Body { 36 | Order order = 1; 37 | } 38 | 39 | Body body = 1; 40 | } 41 | 42 | message AddResponse { 43 | int64 id = 1; 44 | string status = 2; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /grpc-with-business-logic/server/grpc_server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "time" 7 | 8 | "github.com/ekhabarov/blog-code-snippets/grpc-with-business-logic/pb" 9 | "github.com/ekhabarov/blog-code-snippets/grpc-with-business-logic/service" 10 | ) 11 | 12 | // server implements gRPC Server OrderServiceServer interface from 13 | // pb/order.pb.go. 14 | type server struct { 15 | osvc service.OrderSvc 16 | } 17 | 18 | func (s *server) Get(ctx context.Context, req *pb.GetRequest) (*pb.GetResponse, error) { 19 | log.Printf("GET request: %#v\n", req) 20 | o, err := s.osvc.Get(ctx, int(req.Id)) 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | items := []*pb.Item{} 26 | 27 | for _, i := range o.Items { 28 | items = append(items, &pb.Item{ 29 | Id: int64(i.ID), 30 | Name: i.Name, 31 | Qty: int32(i.Qty), 32 | }) 33 | } 34 | 35 | order := &pb.Order{ 36 | Id: int64(o.ID), 37 | Number: o.Num, 38 | Status: o.Status, 39 | CreatedAt: time.Now().Unix(), 40 | Items: items, 41 | } 42 | 43 | return &pb.GetResponse{ 44 | Order: order, 45 | }, nil 46 | } 47 | 48 | func (s *server) Add(ctx context.Context, req *pb.AddRequest) (*pb.AddResponse, error) { 49 | log.Printf("ADD request: %#v\n", req) 50 | o := req.Body.Order 51 | 52 | id, err := s.osvc.Add(ctx, &service.Order{ 53 | ID: int(o.Id), 54 | Num: o.Number, 55 | Status: o.Status, 56 | Items: nil, // skip it again 57 | Comment: "new order", 58 | }) 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | return &pb.AddResponse{ 64 | Id: int64(id), 65 | Status: "added", 66 | }, nil 67 | } 68 | -------------------------------------------------------------------------------- /grpc-with-business-logic/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/ekhabarov/blog-code-snippets/grpc-with-business-logic/pb" 7 | "github.com/ekhabarov/blog-code-snippets/grpc-with-business-logic/service" 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | func main() { 12 | s := grpc.NewServer() 13 | pb.RegisterOrderServiceServer(s, &server{ 14 | osvc: service.New(), 15 | }) 16 | 17 | lis, err := net.Listen("tcp", ":5001") 18 | if err != nil { 19 | return 20 | } 21 | 22 | s.Serve(lis) 23 | } 24 | -------------------------------------------------------------------------------- /grpc-with-business-logic/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "strconv" 7 | ) 8 | 9 | type ( 10 | OrderItem struct { 11 | ID int 12 | Name string 13 | Qty int 14 | State string 15 | } 16 | 17 | Order struct { 18 | ID int 19 | Num string 20 | Status string 21 | Items []OrderItem 22 | Comment string 23 | } 24 | 25 | // OrderSvc is an interface which represents business logic. 26 | OrderSvc interface { 27 | Get(context.Context, int) (*Order, error) 28 | Add(context.Context, *Order) (int, error) 29 | } 30 | ) 31 | 32 | type osvc struct{} 33 | 34 | func New() OrderSvc { 35 | return &osvc{} 36 | } 37 | 38 | // Get returns an Order by ID with OrderItems. 39 | // 40 | // Actually this function have to call repo, but for simplicity it returns faked 41 | // data. 42 | func (s *osvc) Get(ctx context.Context, id int) (*Order, error) { 43 | switch id { 44 | case 1, 2, 3: 45 | items := []OrderItem{} 46 | 47 | for i := 0; i < id; i++ { 48 | items = append(items, OrderItem{ 49 | ID: (i + 1) * 10, 50 | Name: "order_item_" + strconv.Itoa(i), 51 | Qty: (i + 1) * 2, 52 | }) 53 | } 54 | 55 | return &Order{ 56 | ID: id, 57 | Num: "order_" + strconv.Itoa(id), 58 | Status: "created", 59 | Items: items, 60 | Comment: "none", 61 | }, nil 62 | } 63 | 64 | return nil, errors.New("order not found") 65 | } 66 | 67 | // Add returns faked added ID. 68 | func (s *osvc) Add(ctx context.Context, o *Order) (int, error) { 69 | return 5, nil 70 | } 71 | -------------------------------------------------------------------------------- /how-to-bazel/generate-code-with-stringer/.bazelversion: -------------------------------------------------------------------------------- 1 | 6.3.2 2 | -------------------------------------------------------------------------------- /how-to-bazel/generate-code-with-stringer/.gitignore: -------------------------------------------------------------------------------- 1 | bazel-* 2 | -------------------------------------------------------------------------------- /how-to-bazel/generate-code-with-stringer/BUILD: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 3 | 4 | # gazelle:prefix github.com/ekhabarov/blog-code-snippets/how-to-bazel/generate-code-with-stringer 5 | # gazelle:build_file_name BUILD,BUILD.bazel 6 | gazelle(name = "gazelle") 7 | 8 | go_library( 9 | name = "generate-code-with-stringer_lib", 10 | srcs = ["main.go"], 11 | importpath = "github.com/ekhabarov/blog-code-snippets/how-to-bazel/generate-code-with-stringer", 12 | visibility = ["//visibility:private"], 13 | deps = ["//cst"], 14 | ) 15 | 16 | go_binary( 17 | name = "generate-code-with-stringer", 18 | embed = [":generate-code-with-stringer_lib"], 19 | visibility = ["//visibility:public"], 20 | ) 21 | -------------------------------------------------------------------------------- /how-to-bazel/generate-code-with-stringer/README.md: -------------------------------------------------------------------------------- 1 | # How to generate and compile code with Go Stringer tool 2 | 3 | Ready-to-go example base on [Stack overflow](https://stackoverflow.com/questions/66499040/bazel-build-gogenerate-stringer-stringer-cant-happen-constant-is-not-an-i) question. 4 | 5 | 6 | > Stringer is a tool to automate the creation of methods that satisfy the 7 | > fmt.Stringer interface. Given the name of a (signed or unsigned) integer type 8 | > T that has constants defined, stringer will create a new self-contained Go 9 | > source file implementing 10 | ```golang 11 | func (t T) String() string 12 | ``` 13 | 14 | See [docs](https://pkg.go.dev/golang.org/x/tools/cmd/stringer) for more details. 15 | 16 | -------------------------------------------------------------------------------- /how-to-bazel/generate-code-with-stringer/WORKSPACE: -------------------------------------------------------------------------------- 1 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 2 | 3 | http_archive( 4 | name = "io_bazel_rules_go", 5 | sha256 = "dd926a88a564a9246713a9c00b35315f54cbd46b31a26d5d8fb264c07045f05d", 6 | urls = [ 7 | "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.38.1/rules_go-v0.38.1.zip", 8 | "https://github.com/bazelbuild/rules_go/releases/download/v0.38.1/rules_go-v0.38.1.zip", 9 | ], 10 | ) 11 | 12 | load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") 13 | 14 | go_rules_dependencies() 15 | 16 | go_register_toolchains(version = "1.20.3") 17 | 18 | http_archive( 19 | name = "bazel_gazelle", 20 | sha256 = "ecba0f04f96b4960a5b250c8e8eeec42281035970aa8852dda73098274d14a1d", 21 | urls = [ 22 | "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz", 23 | "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz", 24 | ], 25 | ) 26 | 27 | load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") 28 | 29 | gazelle_dependencies() 30 | -------------------------------------------------------------------------------- /how-to-bazel/generate-code-with-stringer/cst/BUILD: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_library") 2 | 3 | go_library( 4 | name = "cst", 5 | srcs = [ 6 | "cst.go", 7 | "cst_stringer.go", 8 | ], 9 | importpath = "github.com/ekhabarov/blog-code-snippets/how-to-bazel/generate-code-with-stringer/cst", 10 | visibility = ["//visibility:public"], 11 | ) 12 | 13 | # Source https://stackoverflow.com/questions/66499040/bazel-build-gogenerate-stringer-stringer-cant-happen-constant-is-not-an-i 14 | genrule( 15 | name = "stringer", 16 | srcs = ["cst.go"], 17 | outs = ["cst_stringer.go"], 18 | cmd = """ 19 | GO_REL_PATH=`dirname $(location @go_sdk//:bin/go)` 20 | GO_ABS_PATH=`cd $$GO_REL_PATH && pwd` 21 | env PATH=$$GO_ABS_PATH HOME=$(GENDIR) \ 22 | $(location @org_golang_x_tools//cmd/stringer) \ 23 | -output=$(OUTS) \ 24 | -type=MyType $(location cst.go) 25 | """, 26 | tools = [ 27 | "@go_sdk//:bin/go", 28 | "@org_golang_x_tools//cmd/stringer", 29 | ], 30 | ) 31 | -------------------------------------------------------------------------------- /how-to-bazel/generate-code-with-stringer/cst/cst.go: -------------------------------------------------------------------------------- 1 | package cst 2 | 3 | type MyType byte 4 | 5 | const ( 6 | ConstA MyType = iota 7 | ConstB 8 | ConstC 9 | ) 10 | -------------------------------------------------------------------------------- /how-to-bazel/generate-code-with-stringer/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ekhabarov/blog-code-snippets/how-to-bazel/generate-code-with-stringer 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /how-to-bazel/generate-code-with-stringer/go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekhabarov/blog-code-snippets/213b5b613fd15dd9e363507e206cf9b2ab31cfcb/how-to-bazel/generate-code-with-stringer/go.sum -------------------------------------------------------------------------------- /how-to-bazel/generate-code-with-stringer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/ekhabarov/blog-code-snippets/how-to-bazel/generate-code-with-stringer/cst" 7 | ) 8 | 9 | func main() { 10 | fmt.Printf("constant: %s\n", cst.ConstA) 11 | fmt.Printf("constant: %s\n", cst.ConstB) 12 | fmt.Printf("constant: %s\n", cst.ConstC) 13 | // Output : 14 | // constant: ConstA 15 | // constant: ConstB 16 | // constant: ConstC 17 | } 18 | -------------------------------------------------------------------------------- /how-to-bazel/genereate-and-compile-go-code/.gitignore: -------------------------------------------------------------------------------- 1 | /bazel-* 2 | -------------------------------------------------------------------------------- /how-to-bazel/genereate-and-compile-go-code/BUILD: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:def.bzl", "gazelle") 2 | 3 | # gazelle:prefix github.com/ekhabarov/hello-world 4 | # gazelle:build_file_name BUILD,BUILD.bazel 5 | gazelle(name = "gazelle") 6 | -------------------------------------------------------------------------------- /how-to-bazel/genereate-and-compile-go-code/README.md: -------------------------------------------------------------------------------- 1 | # How to generate and compile Go code with Bazel 2 | 3 | This is an example of how to generate Go code with external Go binary and 4 | compile it with Bazel. The whole process looks like: 5 | 6 | ![Schema](schema.png) 7 | 8 | [Blog](https://ekhabarov.com/post/how-to-generate-code-with-bazel/) 9 | -------------------------------------------------------------------------------- /how-to-bazel/genereate-and-compile-go-code/WORKSPACE: -------------------------------------------------------------------------------- 1 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 2 | 3 | http_archive( 4 | name = "io_bazel_rules_go", 5 | sha256 = "dd926a88a564a9246713a9c00b35315f54cbd46b31a26d5d8fb264c07045f05d", 6 | urls = [ 7 | "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.38.1/rules_go-v0.38.1.zip", 8 | "https://github.com/bazelbuild/rules_go/releases/download/v0.38.1/rules_go-v0.38.1.zip", 9 | ], 10 | ) 11 | 12 | load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") 13 | 14 | go_rules_dependencies() 15 | 16 | go_register_toolchains(version = "1.20.3") 17 | 18 | http_archive( 19 | name = "bazel_gazelle", 20 | sha256 = "ecba0f04f96b4960a5b250c8e8eeec42281035970aa8852dda73098274d14a1d", 21 | urls = [ 22 | "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz", 23 | "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz", 24 | ], 25 | ) 26 | 27 | load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") 28 | 29 | gazelle_dependencies() 30 | 31 | load("go_deps.bzl", "go_deps") 32 | 33 | go_deps() 34 | -------------------------------------------------------------------------------- /how-to-bazel/genereate-and-compile-go-code/cat/BUILD: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | genrule( 4 | name = "generate_hello_go", 5 | outs = ["hello.go"], 6 | cmd = """ 7 | cat << EOF >> $@ 8 | package main 9 | 10 | import "fmt" 11 | 12 | func main() { 13 | fmt.Printf("Hello World!") 14 | } 15 | EOF 16 | """, 17 | ) 18 | 19 | go_library( 20 | name = "hello-world_lib", 21 | srcs = ["hello.go"], 22 | # srcs = [":generate_hello_go"], # genrule name also can be used here. 23 | importpath = "github.com/ekhabarov/hello-world", 24 | ) 25 | 26 | go_binary( 27 | name = "hello-world", 28 | embed = [":hello-world_lib"], 29 | importpath = "github.com/ekhabarov/hello-world", 30 | ) 31 | -------------------------------------------------------------------------------- /how-to-bazel/genereate-and-compile-go-code/go/BUILD: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | genrule( 4 | name = "generate_hello_go", 5 | outs = ["hello.go"], 6 | cmd = "$(execpath @com_github_ekhabarov_helloworld_generator//:helloworld-generator) > $@", 7 | tools = [ 8 | "@com_github_ekhabarov_helloworld_generator//:helloworld-generator", 9 | ], 10 | ) 11 | 12 | go_library( 13 | name = "hello-world_lib", 14 | srcs = ["hello.go"], 15 | importpath = "github.com/ekhabarov/helloworld-generator", 16 | ) 17 | 18 | go_binary( 19 | name = "hello-world", 20 | embed = [":hello-world_lib"], 21 | importpath = "github.com/ekhabarov/helloworld-generator", 22 | ) 23 | -------------------------------------------------------------------------------- /how-to-bazel/genereate-and-compile-go-code/go_deps.bzl: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:deps.bzl", "go_repository") 2 | 3 | def go_deps(): 4 | go_repository( 5 | name = "com_github_ekhabarov_helloworld_generator", 6 | importpath = "github.com/ekhabarov/helloworld-generator", 7 | sum = "h1:MrREQgX6I0/4cstUhbuqfALzUF3W2Nz8kVZRq6A4q+E=", 8 | version = "v0.0.1", 9 | ) 10 | -------------------------------------------------------------------------------- /how-to-bazel/genereate-and-compile-go-code/schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekhabarov/blog-code-snippets/213b5b613fd15dd9e363507e206cf9b2ab31cfcb/how-to-bazel/genereate-and-compile-go-code/schema.png -------------------------------------------------------------------------------- /ragel/Makefile: -------------------------------------------------------------------------------- 1 | generate: 2 | @ragel -Z -G2 machine.rl -o machine.go 3 | @sed -i "1i // Code generated by ragel. DO NOT EDIT." machine.go 4 | -------------------------------------------------------------------------------- /ragel/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ekhabarov/blog-code-snippets/parser 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/onsi/ginkgo v1.14.2 7 | github.com/onsi/gomega v1.10.4 8 | ) 9 | -------------------------------------------------------------------------------- /ragel/go.sum: -------------------------------------------------------------------------------- 1 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 2 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 3 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 4 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 5 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 6 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 7 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 8 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 9 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 10 | github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= 11 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 12 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 13 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 14 | github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= 15 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 16 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 17 | github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= 18 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 19 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 20 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 21 | github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M= 22 | github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= 23 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 24 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 25 | github.com/onsi/gomega v1.10.4 h1:NiTx7EEvBzu9sFOD1zORteLSt3o8gnlvZZwSE9TnY9U= 26 | github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ= 27 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 28 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 29 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 30 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 31 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 32 | golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= 33 | golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 34 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 35 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 36 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 37 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 38 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 39 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 40 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 41 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 42 | golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 43 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= 44 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 45 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 46 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 47 | golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= 48 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 49 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 50 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 51 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 52 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 53 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 54 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 55 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 56 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 57 | google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= 58 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 59 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 60 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 61 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 62 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 63 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 64 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 65 | gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= 66 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 67 | -------------------------------------------------------------------------------- /ragel/machine.go: -------------------------------------------------------------------------------- 1 | // Code generated by ragel. DO NOT EDIT. 2 | 3 | //line machine.rl:1 4 | package parser 5 | 6 | import ( 7 | "fmt" 8 | "strings" 9 | ) 10 | 11 | //go:generate make generate 12 | 13 | 14 | //line machine.go:14 15 | const phone_start int = 1 16 | const phone_first_final int = 20 17 | const phone_error int = 0 18 | 19 | const phone_en_main int = 1 20 | 21 | 22 | //line machine.rl:78 23 | 24 | 25 | // Machine contains variables used by Ragel auto generated code. 26 | // See Ragel docs for details. 27 | type Machine struct { 28 | // Data to process. 29 | data []byte 30 | // Data pointer. 31 | p int 32 | // Data end pointer. 33 | pe int 34 | // Curent state. 35 | cs int 36 | // End of file pointer. 37 | eof int 38 | // Start of current date block. 39 | pb int 40 | // Current err 41 | err error 42 | } 43 | 44 | // Phone represents parser result and will be filled by Raagel actions. 45 | type Phone struct { 46 | IntCode string 47 | AreaCode string 48 | Number string 49 | } 50 | 51 | // New initialized new Machine structure. 52 | func New() *Machine { 53 | return &Machine{} 54 | } 55 | 56 | // string returns current parsed variable. Variable m.pb should be updated by 57 | // "mark" action, while m.p is a current parser position inside m.data. 58 | func (m *Machine) string() string { 59 | return string(m.data[m.pb:m.p]) 60 | } 61 | 62 | // Parse takes a slice of bytes as an input an fills Phone structure in case 63 | // input is a phone number in one of valid formats. 64 | func (m *Machine) Parse(input []byte) (*Phone, error) { 65 | // Initialize variables required by Ragel. 66 | m.data = input 67 | m.pe = len(input) 68 | m.p = 0 69 | m.pb = 0 70 | m.err = nil 71 | m.eof = len(input) 72 | 73 | phone := &Phone{} 74 | 75 | 76 | //line machine.go:76 77 | { 78 | m.cs = phone_start 79 | } 80 | 81 | //line machine.rl:131 82 | 83 | //line machine.go:83 84 | { 85 | if ( m.p) == ( m.pe) { 86 | goto _test_eof 87 | } 88 | switch m.cs { 89 | case 1: 90 | goto st_case_1 91 | case 0: 92 | goto st_case_0 93 | case 2: 94 | goto st_case_2 95 | case 3: 96 | goto st_case_3 97 | case 4: 98 | goto st_case_4 99 | case 5: 100 | goto st_case_5 101 | case 6: 102 | goto st_case_6 103 | case 7: 104 | goto st_case_7 105 | case 8: 106 | goto st_case_8 107 | case 9: 108 | goto st_case_9 109 | case 10: 110 | goto st_case_10 111 | case 11: 112 | goto st_case_11 113 | case 12: 114 | goto st_case_12 115 | case 13: 116 | goto st_case_13 117 | case 14: 118 | goto st_case_14 119 | case 15: 120 | goto st_case_15 121 | case 20: 122 | goto st_case_20 123 | case 16: 124 | goto st_case_16 125 | case 17: 126 | goto st_case_17 127 | case 18: 128 | goto st_case_18 129 | case 19: 130 | goto st_case_19 131 | } 132 | goto st_out 133 | st_case_1: 134 | switch ( m.data)[( m.p)] { 135 | case 32: 136 | goto st2 137 | case 40: 138 | goto st3 139 | case 43: 140 | goto st18 141 | case 45: 142 | goto st3 143 | case 49: 144 | goto tr4 145 | } 146 | if 50 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 147 | goto tr5 148 | } 149 | goto tr0 150 | tr0: 151 | //line machine.rl:27 152 | 153 | m.err = fmt.Errorf("invalid area code, expected 200..999") 154 | 155 | goto st0 156 | tr8: 157 | //line machine.rl:38 158 | 159 | m.err = fmt.Errorf("invalid phone format: %s", m.data) 160 | 161 | goto st0 162 | //line machine.go:162 163 | st_case_0: 164 | st0: 165 | m.cs = 0 166 | goto _out 167 | tr24: 168 | //line machine.rl:17 169 | 170 | phone.IntCode = m.string() 171 | 172 | goto st2 173 | st2: 174 | if ( m.p)++; ( m.p) == ( m.pe) { 175 | goto _test_eof2 176 | } 177 | st_case_2: 178 | //line machine.go:178 179 | switch ( m.data)[( m.p)] { 180 | case 32: 181 | goto st2 182 | case 40: 183 | goto st3 184 | case 45: 185 | goto st3 186 | } 187 | if 50 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 188 | goto tr5 189 | } 190 | goto tr0 191 | tr25: 192 | //line machine.rl:17 193 | 194 | phone.IntCode = m.string() 195 | 196 | goto st3 197 | st3: 198 | if ( m.p)++; ( m.p) == ( m.pe) { 199 | goto _test_eof3 200 | } 201 | st_case_3: 202 | //line machine.go:202 203 | if 50 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 204 | goto tr5 205 | } 206 | goto tr0 207 | tr5: 208 | //line machine.rl:14 209 | m.pb = m.p 210 | goto st4 211 | tr26: 212 | //line machine.rl:17 213 | 214 | phone.IntCode = m.string() 215 | 216 | //line machine.rl:14 217 | m.pb = m.p 218 | goto st4 219 | st4: 220 | if ( m.p)++; ( m.p) == ( m.pe) { 221 | goto _test_eof4 222 | } 223 | st_case_4: 224 | //line machine.go:224 225 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 226 | goto st5 227 | } 228 | goto tr0 229 | st5: 230 | if ( m.p)++; ( m.p) == ( m.pe) { 231 | goto _test_eof5 232 | } 233 | st_case_5: 234 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 235 | goto st6 236 | } 237 | goto tr0 238 | st6: 239 | if ( m.p)++; ( m.p) == ( m.pe) { 240 | goto _test_eof6 241 | } 242 | st_case_6: 243 | switch ( m.data)[( m.p)] { 244 | case 32: 245 | goto tr9 246 | case 41: 247 | goto tr9 248 | case 45: 249 | goto tr9 250 | } 251 | if 50 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 252 | goto tr10 253 | } 254 | goto tr8 255 | tr9: 256 | //line machine.rl:22 257 | 258 | phone.AreaCode = m.string() 259 | 260 | goto st7 261 | st7: 262 | if ( m.p)++; ( m.p) == ( m.pe) { 263 | goto _test_eof7 264 | } 265 | st_case_7: 266 | //line machine.go:266 267 | if ( m.data)[( m.p)] == 32 { 268 | goto st7 269 | } 270 | if 50 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 271 | goto tr12 272 | } 273 | goto tr8 274 | tr12: 275 | //line machine.rl:14 276 | m.pb = m.p 277 | goto st8 278 | tr10: 279 | //line machine.rl:22 280 | 281 | phone.AreaCode = m.string() 282 | 283 | //line machine.rl:14 284 | m.pb = m.p 285 | goto st8 286 | st8: 287 | if ( m.p)++; ( m.p) == ( m.pe) { 288 | goto _test_eof8 289 | } 290 | st_case_8: 291 | //line machine.go:291 292 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 293 | goto st9 294 | } 295 | goto tr8 296 | st9: 297 | if ( m.p)++; ( m.p) == ( m.pe) { 298 | goto _test_eof9 299 | } 300 | st_case_9: 301 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 302 | goto st10 303 | } 304 | goto tr8 305 | st10: 306 | if ( m.p)++; ( m.p) == ( m.pe) { 307 | goto _test_eof10 308 | } 309 | st_case_10: 310 | switch ( m.data)[( m.p)] { 311 | case 32: 312 | goto st11 313 | case 45: 314 | goto st17 315 | } 316 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 317 | goto st12 318 | } 319 | goto tr8 320 | st11: 321 | if ( m.p)++; ( m.p) == ( m.pe) { 322 | goto _test_eof11 323 | } 324 | st_case_11: 325 | if ( m.data)[( m.p)] == 32 { 326 | goto st11 327 | } 328 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 329 | goto st12 330 | } 331 | goto tr8 332 | st12: 333 | if ( m.p)++; ( m.p) == ( m.pe) { 334 | goto _test_eof12 335 | } 336 | st_case_12: 337 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 338 | goto st13 339 | } 340 | goto tr8 341 | st13: 342 | if ( m.p)++; ( m.p) == ( m.pe) { 343 | goto _test_eof13 344 | } 345 | st_case_13: 346 | switch ( m.data)[( m.p)] { 347 | case 32: 348 | goto st14 349 | case 45: 350 | goto st16 351 | } 352 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 353 | goto st15 354 | } 355 | goto tr8 356 | st14: 357 | if ( m.p)++; ( m.p) == ( m.pe) { 358 | goto _test_eof14 359 | } 360 | st_case_14: 361 | if ( m.data)[( m.p)] == 32 { 362 | goto st14 363 | } 364 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 365 | goto st15 366 | } 367 | goto tr8 368 | st15: 369 | if ( m.p)++; ( m.p) == ( m.pe) { 370 | goto _test_eof15 371 | } 372 | st_case_15: 373 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 374 | goto tr22 375 | } 376 | goto tr8 377 | tr22: 378 | //line machine.rl:43 379 | 380 | if phone.IntCode == ""{ 381 | phone.IntCode = "1" 382 | } 383 | 384 | goto st20 385 | st20: 386 | if ( m.p)++; ( m.p) == ( m.pe) { 387 | goto _test_eof20 388 | } 389 | st_case_20: 390 | //line machine.go:390 391 | goto st0 392 | st16: 393 | if ( m.p)++; ( m.p) == ( m.pe) { 394 | goto _test_eof16 395 | } 396 | st_case_16: 397 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 398 | goto st15 399 | } 400 | goto tr8 401 | st17: 402 | if ( m.p)++; ( m.p) == ( m.pe) { 403 | goto _test_eof17 404 | } 405 | st_case_17: 406 | if 48 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 407 | goto st12 408 | } 409 | goto tr8 410 | st18: 411 | if ( m.p)++; ( m.p) == ( m.pe) { 412 | goto _test_eof18 413 | } 414 | st_case_18: 415 | if ( m.data)[( m.p)] == 49 { 416 | goto tr4 417 | } 418 | goto st0 419 | tr4: 420 | //line machine.rl:14 421 | m.pb = m.p 422 | goto st19 423 | st19: 424 | if ( m.p)++; ( m.p) == ( m.pe) { 425 | goto _test_eof19 426 | } 427 | st_case_19: 428 | //line machine.go:428 429 | switch ( m.data)[( m.p)] { 430 | case 32: 431 | goto tr24 432 | case 40: 433 | goto tr25 434 | case 45: 435 | goto tr25 436 | } 437 | if 50 <= ( m.data)[( m.p)] && ( m.data)[( m.p)] <= 57 { 438 | goto tr26 439 | } 440 | goto tr0 441 | st_out: 442 | _test_eof2: m.cs = 2; goto _test_eof 443 | _test_eof3: m.cs = 3; goto _test_eof 444 | _test_eof4: m.cs = 4; goto _test_eof 445 | _test_eof5: m.cs = 5; goto _test_eof 446 | _test_eof6: m.cs = 6; goto _test_eof 447 | _test_eof7: m.cs = 7; goto _test_eof 448 | _test_eof8: m.cs = 8; goto _test_eof 449 | _test_eof9: m.cs = 9; goto _test_eof 450 | _test_eof10: m.cs = 10; goto _test_eof 451 | _test_eof11: m.cs = 11; goto _test_eof 452 | _test_eof12: m.cs = 12; goto _test_eof 453 | _test_eof13: m.cs = 13; goto _test_eof 454 | _test_eof14: m.cs = 14; goto _test_eof 455 | _test_eof15: m.cs = 15; goto _test_eof 456 | _test_eof20: m.cs = 20; goto _test_eof 457 | _test_eof16: m.cs = 16; goto _test_eof 458 | _test_eof17: m.cs = 17; goto _test_eof 459 | _test_eof18: m.cs = 18; goto _test_eof 460 | _test_eof19: m.cs = 19; goto _test_eof 461 | 462 | _test_eof: {} 463 | if ( m.p) == ( m.eof) { 464 | switch m.cs { 465 | case 1, 2, 3, 4, 5, 19: 466 | //line machine.rl:27 467 | 468 | m.err = fmt.Errorf("invalid area code, expected 200..999") 469 | 470 | case 20: 471 | //line machine.rl:32 472 | 473 | n := strings.ReplaceAll(m.string(), "-","") 474 | phone.Number = strings.ReplaceAll(n, " ","") 475 | 476 | case 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17: 477 | //line machine.rl:38 478 | 479 | m.err = fmt.Errorf("invalid phone format: %s", m.data) 480 | 481 | //line machine.go:481 482 | } 483 | } 484 | 485 | _out: {} 486 | } 487 | 488 | //line machine.rl:132 489 | 490 | if m.err != nil { 491 | return nil, m.err 492 | } 493 | 494 | return phone, m.err 495 | } 496 | 497 | -------------------------------------------------------------------------------- /ragel/machine.rl: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | //go:generate make generate 9 | 10 | %%{ 11 | machine phone; 12 | 13 | # sets the start point for the current value 14 | action mark{ m.pb = m.p } 15 | 16 | # writes international code. 17 | action set_intcode{ 18 | phone.IntCode = m.string() 19 | } 20 | 21 | # writes area code 22 | action set_area{ 23 | phone.AreaCode = m.string() 24 | } 25 | 26 | # return area-related error 27 | action err_area{ 28 | m.err = fmt.Errorf("invalid area code, expected 200..999") 29 | } 30 | 31 | # writes number and replaces all hyphens and spaces. 32 | action set_number{ 33 | n := strings.ReplaceAll(m.string(), "-","") 34 | phone.Number = strings.ReplaceAll(n, " ","") 35 | } 36 | 37 | # return an error when phone with incorrect format. 38 | action err_phone{ 39 | m.err = fmt.Errorf("invalid phone format: %s", m.data) 40 | } 41 | 42 | # sets default international code. 43 | action set_defaults{ 44 | if phone.IntCode == ""{ 45 | phone.IntCode = "1" 46 | } 47 | } 48 | 49 | sp = ' '; 50 | hy = (sp* | '-'); 51 | hbl = ( hy | '(' ); 52 | hbr = ( hy | ')' ); 53 | 54 | # defines an international code: +1,1 55 | int = '+'? '1' >mark %set_intcode; 56 | 57 | # defines a range 200..999 58 | nxx = ('2'..'9' . digit{2}); 59 | 60 | # defines an area code with separators: (NXX), -NXX- 61 | area = hbl? nxx >mark %set_area @err(err_area) hbr?; 62 | 63 | # defines phone number in range 2000000..9999999, with an optional separators. 64 | number = (nxx hy? digit{2} hy? digit{2}) >mark %set_number @err(err_phone); 65 | 66 | # defines main machine for a phone. 67 | main := int? sp* area sp* number @set_defaults; 68 | 69 | write data; 70 | 71 | access m.; 72 | 73 | variable p m.p; 74 | variable pe m.pe; 75 | variable eof m.eof; 76 | variable data m.data; 77 | 78 | }%% 79 | 80 | // Machine contains variables used by Ragel auto generated code. 81 | // See Ragel docs for details. 82 | type Machine struct { 83 | // Data to process. 84 | data []byte 85 | // Data pointer. 86 | p int 87 | // Data end pointer. 88 | pe int 89 | // Curent state. 90 | cs int 91 | // End of file pointer. 92 | eof int 93 | // Start of current date block. 94 | pb int 95 | // Current err 96 | err error 97 | } 98 | 99 | // Phone represents parser result and will be filled by Raagel actions. 100 | type Phone struct { 101 | IntCode string 102 | AreaCode string 103 | Number string 104 | } 105 | 106 | // New initialized new Machine structure. 107 | func New() *Machine { 108 | return &Machine{} 109 | } 110 | 111 | // string returns current parsed variable. Variable m.pb should be updated by 112 | // "mark" action, while m.p is a current parser position inside m.data. 113 | func (m *Machine) string() string { 114 | return string(m.data[m.pb:m.p]) 115 | } 116 | 117 | // Parse takes a slice of bytes as an input an fills Phone structure in case 118 | // input is a phone number in one of valid formats. 119 | func (m *Machine) Parse(input []byte) (*Phone, error) { 120 | // Initialize variables required by Ragel. 121 | m.data = input 122 | m.pe = len(input) 123 | m.p = 0 124 | m.pb = 0 125 | m.err = nil 126 | m.eof = len(input) 127 | 128 | phone := &Phone{} 129 | 130 | %% write init; 131 | %% write exec; 132 | 133 | if m.err != nil { 134 | return nil, m.err 135 | } 136 | 137 | return phone, m.err 138 | } 139 | 140 | -------------------------------------------------------------------------------- /ragel/machine_test.go: -------------------------------------------------------------------------------- 1 | package parser_test 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/ekhabarov/blog-code-snippets/parser" 7 | 8 | . "github.com/onsi/ginkgo" 9 | . "github.com/onsi/ginkgo/extensions/table" 10 | . "github.com/onsi/gomega" 11 | . "github.com/onsi/gomega/gstruct" 12 | ) 13 | 14 | var _ = Describe("Machine", func() { 15 | 16 | Describe("Parse", func() { 17 | 18 | var m = parser.New() 19 | 20 | DescribeTable("Correct values", 21 | func() { 22 | phone := CurrentGinkgoTestDescription().TestText 23 | p, err := m.Parse([]byte(phone)) 24 | Expect(err).NotTo(HaveOccurred()) 25 | 26 | Expect(*p).To(MatchAllFields(Fields{ 27 | "IntCode": Equal("1"), 28 | "AreaCode": Equal("555"), 29 | "Number": Equal("2334567"), 30 | })) 31 | }, 32 | 33 | Entry("+1 (555) 2334567"), 34 | Entry("+1(555)2334567"), 35 | Entry("+1 (555) 2334567"), 36 | Entry("+1 (555) 233-4567"), 37 | Entry("+1 (555) 233-45-67"), 38 | Entry("+1 (555) 233 45-67"), 39 | Entry("+1(555)233-4567"), 40 | Entry("+15552334567"), 41 | Entry("+1-555-233-4567"), 42 | 43 | Entry("1 (555) 2334567"), 44 | Entry("1(555)2334567"), 45 | Entry("1 (555) 2334567"), 46 | Entry("1 (555) 233-4567"), 47 | Entry("1 (555) 233-45-67"), 48 | Entry("1 (555) 233 45-67"), 49 | Entry("1(555)233-4567"), 50 | Entry("15552334567"), 51 | 52 | Entry("(555) 233-4567"), 53 | Entry("(555)233-4567"), 54 | Entry("5552334567"), 55 | Entry("555-233-4567"), 56 | Entry(" 555 233 45 67"), 57 | ) 58 | 59 | DescribeTable("Area error", 60 | func() { 61 | phone := CurrentGinkgoTestDescription().TestText 62 | p, err := m.Parse([]byte(phone)) 63 | Expect(p).To(BeNil()) 64 | Expect(err).To(MatchError("invalid area code, expected 200..999")) 65 | }, 66 | 67 | Entry("+1 (155) 2334567"), 68 | Entry("+1 (A55) 2334567"), 69 | Entry("11992223344"), 70 | Entry("11992223344"), 71 | ) 72 | 73 | DescribeTable("Invalid phone format", 74 | func() { 75 | phone := CurrentGinkgoTestDescription().TestText 76 | p, err := m.Parse([]byte(phone)) 77 | Expect(p).To(BeNil()) 78 | Expect(err).To(MatchError(fmt.Sprintf("invalid phone format: %s", phone))) 79 | }, 80 | 81 | Entry("+1 (555) 1334567"), 82 | Entry("+1(555)23!4567"), 83 | Entry("+1(555+2334567"), 84 | Entry("+1(555) 1234"), 85 | Entry("+1(555) 33 44 55"), 86 | ) 87 | }) 88 | }) 89 | -------------------------------------------------------------------------------- /ragel/ragel_suite_test.go: -------------------------------------------------------------------------------- 1 | package parser_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | func TestRagel(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Parser Suite") 13 | } 14 | -------------------------------------------------------------------------------- /simple-grpc-service/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | 8 | "github.com/ekhabarov/blog-code-snippets/simple-grpc-service/pb" 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | func main() { 13 | cc, err := grpc.Dial("127.0.0.1:5001", grpc.WithInsecure()) 14 | if err != nil { 15 | log.Fatal(err) 16 | } 17 | defer cc.Close() 18 | 19 | client := pb.NewCalcClient(cc) 20 | resp, err := client.Add(context.Background(), &pb.Request{A: 2, B: 2}) 21 | if err != nil { 22 | log.Fatal(err) 23 | } 24 | 25 | fmt.Printf("response is: %d\n", resp.C) 26 | } 27 | -------------------------------------------------------------------------------- /simple-grpc-service/pb/calc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: calc.proto 3 | 4 | package pb 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | type Request struct { 28 | A int32 `protobuf:"varint,1,opt,name=a,proto3" json:"a,omitempty"` 29 | B int32 `protobuf:"varint,2,opt,name=b,proto3" json:"b,omitempty"` 30 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 31 | XXX_unrecognized []byte `json:"-"` 32 | XXX_sizecache int32 `json:"-"` 33 | } 34 | 35 | func (m *Request) Reset() { *m = Request{} } 36 | func (m *Request) String() string { return proto.CompactTextString(m) } 37 | func (*Request) ProtoMessage() {} 38 | func (*Request) Descriptor() ([]byte, []int) { 39 | return fileDescriptor_a2b9900dc883ea68, []int{0} 40 | } 41 | 42 | func (m *Request) XXX_Unmarshal(b []byte) error { 43 | return xxx_messageInfo_Request.Unmarshal(m, b) 44 | } 45 | func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 46 | return xxx_messageInfo_Request.Marshal(b, m, deterministic) 47 | } 48 | func (m *Request) XXX_Merge(src proto.Message) { 49 | xxx_messageInfo_Request.Merge(m, src) 50 | } 51 | func (m *Request) XXX_Size() int { 52 | return xxx_messageInfo_Request.Size(m) 53 | } 54 | func (m *Request) XXX_DiscardUnknown() { 55 | xxx_messageInfo_Request.DiscardUnknown(m) 56 | } 57 | 58 | var xxx_messageInfo_Request proto.InternalMessageInfo 59 | 60 | func (m *Request) GetA() int32 { 61 | if m != nil { 62 | return m.A 63 | } 64 | return 0 65 | } 66 | 67 | func (m *Request) GetB() int32 { 68 | if m != nil { 69 | return m.B 70 | } 71 | return 0 72 | } 73 | 74 | type Response struct { 75 | C int32 `protobuf:"varint,3,opt,name=c,proto3" json:"c,omitempty"` 76 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 77 | XXX_unrecognized []byte `json:"-"` 78 | XXX_sizecache int32 `json:"-"` 79 | } 80 | 81 | func (m *Response) Reset() { *m = Response{} } 82 | func (m *Response) String() string { return proto.CompactTextString(m) } 83 | func (*Response) ProtoMessage() {} 84 | func (*Response) Descriptor() ([]byte, []int) { 85 | return fileDescriptor_a2b9900dc883ea68, []int{1} 86 | } 87 | 88 | func (m *Response) XXX_Unmarshal(b []byte) error { 89 | return xxx_messageInfo_Response.Unmarshal(m, b) 90 | } 91 | func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 92 | return xxx_messageInfo_Response.Marshal(b, m, deterministic) 93 | } 94 | func (m *Response) XXX_Merge(src proto.Message) { 95 | xxx_messageInfo_Response.Merge(m, src) 96 | } 97 | func (m *Response) XXX_Size() int { 98 | return xxx_messageInfo_Response.Size(m) 99 | } 100 | func (m *Response) XXX_DiscardUnknown() { 101 | xxx_messageInfo_Response.DiscardUnknown(m) 102 | } 103 | 104 | var xxx_messageInfo_Response proto.InternalMessageInfo 105 | 106 | func (m *Response) GetC() int32 { 107 | if m != nil { 108 | return m.C 109 | } 110 | return 0 111 | } 112 | 113 | func init() { 114 | proto.RegisterType((*Request)(nil), "Request") 115 | proto.RegisterType((*Response)(nil), "Response") 116 | } 117 | 118 | func init() { proto.RegisterFile("calc.proto", fileDescriptor_a2b9900dc883ea68) } 119 | 120 | var fileDescriptor_a2b9900dc883ea68 = []byte{ 121 | // 125 bytes of a gzipped FileDescriptorProto 122 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4e, 0xcc, 0x49, 123 | 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x52, 0xe5, 0x62, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 124 | 0x2e, 0x11, 0xe2, 0xe1, 0x62, 0x4c, 0x94, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0d, 0x62, 0x4c, 0x04, 125 | 0xf1, 0x92, 0x24, 0x98, 0x20, 0xbc, 0x24, 0x25, 0x09, 0x2e, 0x8e, 0xa0, 0xd4, 0xe2, 0x82, 0xfc, 126 | 0xbc, 0xe2, 0x54, 0x90, 0x4c, 0xb2, 0x04, 0x33, 0x44, 0x26, 0xd9, 0x48, 0x89, 0x8b, 0xc5, 0x39, 127 | 0x31, 0x27, 0x59, 0x48, 0x8a, 0x8b, 0xd9, 0x31, 0x25, 0x45, 0x88, 0x43, 0x0f, 0x6a, 0x9c, 0x14, 128 | 0xa7, 0x1e, 0x4c, 0x87, 0x13, 0x4b, 0x14, 0x53, 0x41, 0x52, 0x12, 0x1b, 0xd8, 0x46, 0x63, 0x40, 129 | 0x00, 0x00, 0x00, 0xff, 0xff, 0x15, 0xcc, 0xa0, 0x54, 0x7f, 0x00, 0x00, 0x00, 130 | } 131 | 132 | // Reference imports to suppress errors if they are not otherwise used. 133 | var _ context.Context 134 | var _ grpc.ClientConn 135 | 136 | // This is a compile-time assertion to ensure that this generated file 137 | // is compatible with the grpc package it is being compiled against. 138 | const _ = grpc.SupportPackageIsVersion4 139 | 140 | // CalcClient is the client API for Calc service. 141 | // 142 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 143 | type CalcClient interface { 144 | Add(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) 145 | } 146 | 147 | type calcClient struct { 148 | cc *grpc.ClientConn 149 | } 150 | 151 | func NewCalcClient(cc *grpc.ClientConn) CalcClient { 152 | return &calcClient{cc} 153 | } 154 | 155 | func (c *calcClient) Add(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { 156 | out := new(Response) 157 | err := c.cc.Invoke(ctx, "/Calc/Add", in, out, opts...) 158 | if err != nil { 159 | return nil, err 160 | } 161 | return out, nil 162 | } 163 | 164 | // CalcServer is the server API for Calc service. 165 | type CalcServer interface { 166 | Add(context.Context, *Request) (*Response, error) 167 | } 168 | 169 | // UnimplementedCalcServer can be embedded to have forward compatible implementations. 170 | type UnimplementedCalcServer struct { 171 | } 172 | 173 | func (*UnimplementedCalcServer) Add(ctx context.Context, req *Request) (*Response, error) { 174 | return nil, status.Errorf(codes.Unimplemented, "method Add not implemented") 175 | } 176 | 177 | func RegisterCalcServer(s *grpc.Server, srv CalcServer) { 178 | s.RegisterService(&_Calc_serviceDesc, srv) 179 | } 180 | 181 | func _Calc_Add_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 182 | in := new(Request) 183 | if err := dec(in); err != nil { 184 | return nil, err 185 | } 186 | if interceptor == nil { 187 | return srv.(CalcServer).Add(ctx, in) 188 | } 189 | info := &grpc.UnaryServerInfo{ 190 | Server: srv, 191 | FullMethod: "/Calc/Add", 192 | } 193 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 194 | return srv.(CalcServer).Add(ctx, req.(*Request)) 195 | } 196 | return interceptor(ctx, in, info, handler) 197 | } 198 | 199 | var _Calc_serviceDesc = grpc.ServiceDesc{ 200 | ServiceName: "Calc", 201 | HandlerType: (*CalcServer)(nil), 202 | Methods: []grpc.MethodDesc{ 203 | { 204 | MethodName: "Add", 205 | Handler: _Calc_Add_Handler, 206 | }, 207 | }, 208 | Streams: []grpc.StreamDesc{}, 209 | Metadata: "calc.proto", 210 | } 211 | -------------------------------------------------------------------------------- /simple-grpc-service/pb/calc.proto: -------------------------------------------------------------------------------- 1 | // Generate Golang code with 2 | // protoc --go_out=plugins=grpc:. ./calc.proto 3 | 4 | syntax = "proto3"; 5 | option go_package = "pb"; 6 | 7 | message Request { 8 | int32 a = 1; 9 | int32 b = 2; 10 | } 11 | 12 | message Response { 13 | int32 c = 3; 14 | } 15 | 16 | service Calc { 17 | rpc Add (Request) returns (Response); 18 | } 19 | -------------------------------------------------------------------------------- /simple-grpc-service/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "net" 7 | 8 | "github.com/ekhabarov/blog-code-snippets/simple-grpc-service/pb" 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | // server implements gRPC Server CalcServer interface from pb/calc.pb.go 13 | type server struct{} 14 | 15 | func (s *server) Add(ctx context.Context, req *pb.Request) (*pb.Response, error) { 16 | fmt.Printf("got request: A = %d, B = %d\n", req.A, req.B) 17 | return &pb.Response{ 18 | C: req.A + req.B, 19 | }, nil 20 | } 21 | 22 | func main() { 23 | s := grpc.NewServer() 24 | pb.RegisterCalcServer(s, &server{}) 25 | 26 | lis, err := net.Listen("tcp", ":5001") 27 | if err != nil { 28 | return 29 | } 30 | 31 | s.Serve(lis) 32 | } 33 | -------------------------------------------------------------------------------- /wire/Makefile: -------------------------------------------------------------------------------- 1 | proto: 2 | protoc -I . --go_out=plugins=grpc:. pb/entity.proto 3 | -------------------------------------------------------------------------------- /wire/app.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | "wire/rpci" 6 | 7 | "google.golang.org/grpc" 8 | ) 9 | 10 | // App contains minimal list of dependencies to be able to start an application. 11 | type App struct { 12 | // listener is a TCP listener which is used by gRPC server. 13 | listener net.Listener 14 | // gRPC serer itself. 15 | gsrv *grpc.Server 16 | // gRPC server implementation. It's not used here directly, but it must be 17 | // initialized for registering. gRPC server. 18 | rpcImpl *rpci.Server 19 | } 20 | 21 | // Start start gRPC server. 22 | func (a App) Start() error { 23 | return a.gsrv.Serve(a.listener) 24 | } 25 | -------------------------------------------------------------------------------- /wire/go.mod: -------------------------------------------------------------------------------- 1 | module wire 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/golang/protobuf v1.4.1 7 | github.com/google/wire v0.4.0 8 | google.golang.org/grpc v1.30.0 9 | google.golang.org/protobuf v1.25.0 10 | ) 11 | -------------------------------------------------------------------------------- /wire/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/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 6 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 7 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 8 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 9 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 10 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 11 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 12 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 13 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 14 | github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= 15 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 16 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 17 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 18 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 19 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 20 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 21 | github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= 22 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 23 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 24 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 25 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 26 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 27 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 28 | github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= 29 | github.com/google/wire v0.4.0 h1:kXcsA/rIGzJImVqPdhfnr6q0xsS9gU0515q1EPpJ9fE= 30 | github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= 31 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 32 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 33 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 34 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 35 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 36 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 37 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 38 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 39 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 40 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 41 | golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= 42 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 43 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 44 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 45 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 46 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 47 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 48 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= 49 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 50 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 51 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 52 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 53 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 54 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 55 | golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 56 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 57 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 58 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 59 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 60 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 61 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= 62 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 63 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= 64 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 65 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 66 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 67 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 68 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 69 | google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= 70 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 71 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 72 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 73 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 74 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 75 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 76 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 77 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 78 | google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= 79 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 80 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 81 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 82 | -------------------------------------------------------------------------------- /wire/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | app, err := initApp() 5 | must(err) 6 | 7 | must(app.Start()) 8 | } 9 | 10 | func must(err error) { 11 | if err != nil { 12 | panic(err) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /wire/pb/entity.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.24.0 4 | // protoc v3.12.0 5 | // source: pb/entity.proto 6 | 7 | package pb 8 | 9 | import ( 10 | context "context" 11 | proto "github.com/golang/protobuf/proto" 12 | grpc "google.golang.org/grpc" 13 | codes "google.golang.org/grpc/codes" 14 | status "google.golang.org/grpc/status" 15 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 16 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 17 | reflect "reflect" 18 | sync "sync" 19 | ) 20 | 21 | const ( 22 | // Verify that this generated code is sufficiently up-to-date. 23 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 24 | // Verify that runtime/protoimpl is sufficiently up-to-date. 25 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 26 | ) 27 | 28 | // This is a compile-time assertion that a sufficiently up-to-date version 29 | // of the legacy proto package is being used. 30 | const _ = proto.ProtoPackageIsVersion4 31 | 32 | type EntityByIDRequest struct { 33 | state protoimpl.MessageState 34 | sizeCache protoimpl.SizeCache 35 | unknownFields protoimpl.UnknownFields 36 | 37 | Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 38 | } 39 | 40 | func (x *EntityByIDRequest) Reset() { 41 | *x = EntityByIDRequest{} 42 | if protoimpl.UnsafeEnabled { 43 | mi := &file_pb_entity_proto_msgTypes[0] 44 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 45 | ms.StoreMessageInfo(mi) 46 | } 47 | } 48 | 49 | func (x *EntityByIDRequest) String() string { 50 | return protoimpl.X.MessageStringOf(x) 51 | } 52 | 53 | func (*EntityByIDRequest) ProtoMessage() {} 54 | 55 | func (x *EntityByIDRequest) ProtoReflect() protoreflect.Message { 56 | mi := &file_pb_entity_proto_msgTypes[0] 57 | if protoimpl.UnsafeEnabled && x != nil { 58 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 59 | if ms.LoadMessageInfo() == nil { 60 | ms.StoreMessageInfo(mi) 61 | } 62 | return ms 63 | } 64 | return mi.MessageOf(x) 65 | } 66 | 67 | // Deprecated: Use EntityByIDRequest.ProtoReflect.Descriptor instead. 68 | func (*EntityByIDRequest) Descriptor() ([]byte, []int) { 69 | return file_pb_entity_proto_rawDescGZIP(), []int{0} 70 | } 71 | 72 | func (x *EntityByIDRequest) GetId() int64 { 73 | if x != nil { 74 | return x.Id 75 | } 76 | return 0 77 | } 78 | 79 | type EntityByIDResponse struct { 80 | state protoimpl.MessageState 81 | sizeCache protoimpl.SizeCache 82 | unknownFields protoimpl.UnknownFields 83 | 84 | Entity *Entity `protobuf:"bytes,1,opt,name=entity,proto3" json:"entity,omitempty"` 85 | } 86 | 87 | func (x *EntityByIDResponse) Reset() { 88 | *x = EntityByIDResponse{} 89 | if protoimpl.UnsafeEnabled { 90 | mi := &file_pb_entity_proto_msgTypes[1] 91 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 92 | ms.StoreMessageInfo(mi) 93 | } 94 | } 95 | 96 | func (x *EntityByIDResponse) String() string { 97 | return protoimpl.X.MessageStringOf(x) 98 | } 99 | 100 | func (*EntityByIDResponse) ProtoMessage() {} 101 | 102 | func (x *EntityByIDResponse) ProtoReflect() protoreflect.Message { 103 | mi := &file_pb_entity_proto_msgTypes[1] 104 | if protoimpl.UnsafeEnabled && x != nil { 105 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 106 | if ms.LoadMessageInfo() == nil { 107 | ms.StoreMessageInfo(mi) 108 | } 109 | return ms 110 | } 111 | return mi.MessageOf(x) 112 | } 113 | 114 | // Deprecated: Use EntityByIDResponse.ProtoReflect.Descriptor instead. 115 | func (*EntityByIDResponse) Descriptor() ([]byte, []int) { 116 | return file_pb_entity_proto_rawDescGZIP(), []int{1} 117 | } 118 | 119 | func (x *EntityByIDResponse) GetEntity() *Entity { 120 | if x != nil { 121 | return x.Entity 122 | } 123 | return nil 124 | } 125 | 126 | type Entity struct { 127 | state protoimpl.MessageState 128 | sizeCache protoimpl.SizeCache 129 | unknownFields protoimpl.UnknownFields 130 | 131 | Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` 132 | Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` 133 | } 134 | 135 | func (x *Entity) Reset() { 136 | *x = Entity{} 137 | if protoimpl.UnsafeEnabled { 138 | mi := &file_pb_entity_proto_msgTypes[2] 139 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 140 | ms.StoreMessageInfo(mi) 141 | } 142 | } 143 | 144 | func (x *Entity) String() string { 145 | return protoimpl.X.MessageStringOf(x) 146 | } 147 | 148 | func (*Entity) ProtoMessage() {} 149 | 150 | func (x *Entity) ProtoReflect() protoreflect.Message { 151 | mi := &file_pb_entity_proto_msgTypes[2] 152 | if protoimpl.UnsafeEnabled && x != nil { 153 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 154 | if ms.LoadMessageInfo() == nil { 155 | ms.StoreMessageInfo(mi) 156 | } 157 | return ms 158 | } 159 | return mi.MessageOf(x) 160 | } 161 | 162 | // Deprecated: Use Entity.ProtoReflect.Descriptor instead. 163 | func (*Entity) Descriptor() ([]byte, []int) { 164 | return file_pb_entity_proto_rawDescGZIP(), []int{2} 165 | } 166 | 167 | func (x *Entity) GetId() int64 { 168 | if x != nil { 169 | return x.Id 170 | } 171 | return 0 172 | } 173 | 174 | func (x *Entity) GetName() string { 175 | if x != nil { 176 | return x.Name 177 | } 178 | return "" 179 | } 180 | 181 | var File_pb_entity_proto protoreflect.FileDescriptor 182 | 183 | var file_pb_entity_proto_rawDesc = []byte{ 184 | 0x0a, 0x0f, 0x70, 0x62, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 185 | 0x6f, 0x12, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x23, 0x0a, 0x11, 0x45, 0x6e, 0x74, 186 | 0x69, 0x74, 0x79, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 187 | 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3c, 188 | 0x0a, 0x12, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 189 | 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 190 | 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 191 | 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x2c, 0x0a, 0x06, 192 | 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 193 | 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 194 | 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x32, 0x50, 0x0a, 0x09, 0x45, 0x6e, 195 | 0x74, 0x69, 0x74, 0x79, 0x52, 0x50, 0x43, 0x12, 0x43, 0x0a, 0x0a, 0x45, 0x6e, 0x74, 0x69, 0x74, 196 | 0x79, 0x42, 0x79, 0x49, 0x44, 0x12, 0x19, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 197 | 0x6e, 0x74, 0x69, 0x74, 0x79, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 198 | 0x1a, 0x1a, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 199 | 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x04, 0x5a, 0x02, 200 | 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 201 | } 202 | 203 | var ( 204 | file_pb_entity_proto_rawDescOnce sync.Once 205 | file_pb_entity_proto_rawDescData = file_pb_entity_proto_rawDesc 206 | ) 207 | 208 | func file_pb_entity_proto_rawDescGZIP() []byte { 209 | file_pb_entity_proto_rawDescOnce.Do(func() { 210 | file_pb_entity_proto_rawDescData = protoimpl.X.CompressGZIP(file_pb_entity_proto_rawDescData) 211 | }) 212 | return file_pb_entity_proto_rawDescData 213 | } 214 | 215 | var file_pb_entity_proto_msgTypes = make([]protoimpl.MessageInfo, 3) 216 | var file_pb_entity_proto_goTypes = []interface{}{ 217 | (*EntityByIDRequest)(nil), // 0: entity.EntityByIDRequest 218 | (*EntityByIDResponse)(nil), // 1: entity.EntityByIDResponse 219 | (*Entity)(nil), // 2: entity.Entity 220 | } 221 | var file_pb_entity_proto_depIdxs = []int32{ 222 | 2, // 0: entity.EntityByIDResponse.entity:type_name -> entity.Entity 223 | 0, // 1: entity.EntityRPC.EntityByID:input_type -> entity.EntityByIDRequest 224 | 1, // 2: entity.EntityRPC.EntityByID:output_type -> entity.EntityByIDResponse 225 | 2, // [2:3] is the sub-list for method output_type 226 | 1, // [1:2] is the sub-list for method input_type 227 | 1, // [1:1] is the sub-list for extension type_name 228 | 1, // [1:1] is the sub-list for extension extendee 229 | 0, // [0:1] is the sub-list for field type_name 230 | } 231 | 232 | func init() { file_pb_entity_proto_init() } 233 | func file_pb_entity_proto_init() { 234 | if File_pb_entity_proto != nil { 235 | return 236 | } 237 | if !protoimpl.UnsafeEnabled { 238 | file_pb_entity_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 239 | switch v := v.(*EntityByIDRequest); i { 240 | case 0: 241 | return &v.state 242 | case 1: 243 | return &v.sizeCache 244 | case 2: 245 | return &v.unknownFields 246 | default: 247 | return nil 248 | } 249 | } 250 | file_pb_entity_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 251 | switch v := v.(*EntityByIDResponse); i { 252 | case 0: 253 | return &v.state 254 | case 1: 255 | return &v.sizeCache 256 | case 2: 257 | return &v.unknownFields 258 | default: 259 | return nil 260 | } 261 | } 262 | file_pb_entity_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 263 | switch v := v.(*Entity); i { 264 | case 0: 265 | return &v.state 266 | case 1: 267 | return &v.sizeCache 268 | case 2: 269 | return &v.unknownFields 270 | default: 271 | return nil 272 | } 273 | } 274 | } 275 | type x struct{} 276 | out := protoimpl.TypeBuilder{ 277 | File: protoimpl.DescBuilder{ 278 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 279 | RawDescriptor: file_pb_entity_proto_rawDesc, 280 | NumEnums: 0, 281 | NumMessages: 3, 282 | NumExtensions: 0, 283 | NumServices: 1, 284 | }, 285 | GoTypes: file_pb_entity_proto_goTypes, 286 | DependencyIndexes: file_pb_entity_proto_depIdxs, 287 | MessageInfos: file_pb_entity_proto_msgTypes, 288 | }.Build() 289 | File_pb_entity_proto = out.File 290 | file_pb_entity_proto_rawDesc = nil 291 | file_pb_entity_proto_goTypes = nil 292 | file_pb_entity_proto_depIdxs = nil 293 | } 294 | 295 | // Reference imports to suppress errors if they are not otherwise used. 296 | var _ context.Context 297 | var _ grpc.ClientConnInterface 298 | 299 | // This is a compile-time assertion to ensure that this generated file 300 | // is compatible with the grpc package it is being compiled against. 301 | const _ = grpc.SupportPackageIsVersion6 302 | 303 | // EntityRPCClient is the client API for EntityRPC service. 304 | // 305 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 306 | type EntityRPCClient interface { 307 | EntityByID(ctx context.Context, in *EntityByIDRequest, opts ...grpc.CallOption) (*EntityByIDResponse, error) 308 | } 309 | 310 | type entityRPCClient struct { 311 | cc grpc.ClientConnInterface 312 | } 313 | 314 | func NewEntityRPCClient(cc grpc.ClientConnInterface) EntityRPCClient { 315 | return &entityRPCClient{cc} 316 | } 317 | 318 | func (c *entityRPCClient) EntityByID(ctx context.Context, in *EntityByIDRequest, opts ...grpc.CallOption) (*EntityByIDResponse, error) { 319 | out := new(EntityByIDResponse) 320 | err := c.cc.Invoke(ctx, "/entity.EntityRPC/EntityByID", in, out, opts...) 321 | if err != nil { 322 | return nil, err 323 | } 324 | return out, nil 325 | } 326 | 327 | // EntityRPCServer is the server API for EntityRPC service. 328 | type EntityRPCServer interface { 329 | EntityByID(context.Context, *EntityByIDRequest) (*EntityByIDResponse, error) 330 | } 331 | 332 | // UnimplementedEntityRPCServer can be embedded to have forward compatible implementations. 333 | type UnimplementedEntityRPCServer struct { 334 | } 335 | 336 | func (*UnimplementedEntityRPCServer) EntityByID(context.Context, *EntityByIDRequest) (*EntityByIDResponse, error) { 337 | return nil, status.Errorf(codes.Unimplemented, "method EntityByID not implemented") 338 | } 339 | 340 | func RegisterEntityRPCServer(s *grpc.Server, srv EntityRPCServer) { 341 | s.RegisterService(&_EntityRPC_serviceDesc, srv) 342 | } 343 | 344 | func _EntityRPC_EntityByID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 345 | in := new(EntityByIDRequest) 346 | if err := dec(in); err != nil { 347 | return nil, err 348 | } 349 | if interceptor == nil { 350 | return srv.(EntityRPCServer).EntityByID(ctx, in) 351 | } 352 | info := &grpc.UnaryServerInfo{ 353 | Server: srv, 354 | FullMethod: "/entity.EntityRPC/EntityByID", 355 | } 356 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 357 | return srv.(EntityRPCServer).EntityByID(ctx, req.(*EntityByIDRequest)) 358 | } 359 | return interceptor(ctx, in, info, handler) 360 | } 361 | 362 | var _EntityRPC_serviceDesc = grpc.ServiceDesc{ 363 | ServiceName: "entity.EntityRPC", 364 | HandlerType: (*EntityRPCServer)(nil), 365 | Methods: []grpc.MethodDesc{ 366 | { 367 | MethodName: "EntityByID", 368 | Handler: _EntityRPC_EntityByID_Handler, 369 | }, 370 | }, 371 | Streams: []grpc.StreamDesc{}, 372 | Metadata: "pb/entity.proto", 373 | } 374 | -------------------------------------------------------------------------------- /wire/pb/entity.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package entity; 3 | 4 | option go_package = "pb"; 5 | 6 | service EntityRPC { 7 | rpc EntityByID(EntityByIDRequest) returns (EntityByIDResponse); 8 | } 9 | 10 | message EntityByIDRequest { 11 | int64 id = 1; 12 | } 13 | 14 | message EntityByIDResponse { 15 | Entity entity = 1; 16 | } 17 | 18 | message Entity { 19 | int64 id = 1; 20 | string name = 2; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /wire/repo/provider.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import "github.com/google/wire" 4 | 5 | var Provider = wire.NewSet( 6 | // here we binds concrete type *DB satisfies a dependency of type Database. 7 | New, wire.Bind(new(Database), new(*DB)), 8 | ) 9 | -------------------------------------------------------------------------------- /wire/repo/repo.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import "database/sql" 4 | 5 | type Entity struct { 6 | ID int 7 | Name string 8 | } 9 | 10 | type Database interface { 11 | GetEntity(id int) (*Entity, error) 12 | } 13 | 14 | type DB struct { 15 | db *sql.DB 16 | } 17 | 18 | func New(db *sql.DB) *DB { 19 | return &DB{db: db} 20 | } 21 | 22 | func (DB) GetEntity(id int) (*Entity, error) { 23 | return &Entity{}, nil 24 | } 25 | -------------------------------------------------------------------------------- /wire/rpci/rpci.go: -------------------------------------------------------------------------------- 1 | package rpci 2 | 3 | import ( 4 | "context" 5 | "wire/pb" 6 | "wire/service" 7 | 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | type Server struct { 12 | xlogic service.Xlogic 13 | } 14 | 15 | func New(x service.Xlogic, gsrv *grpc.Server) *Server { 16 | s := &Server{xlogic: x} 17 | pb.RegisterEntityRPCServer(gsrv, s) 18 | 19 | return s 20 | } 21 | 22 | func (s *Server) EntityByID(ctx context.Context, req *pb.EntityByIDRequest) (*pb.EntityByIDResponse, error) { 23 | xe, err := s.xlogic.GetEntity(int(req.Id)) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | return &pb.EntityByIDResponse{Entity: &pb.Entity{ 29 | Id: int64(xe.ID), 30 | Name: xe.Name, 31 | }}, nil 32 | } 33 | -------------------------------------------------------------------------------- /wire/service/provider.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import "github.com/google/wire" 4 | 5 | var Provider = wire.NewSet( 6 | // here we binds concrete type *Service satisfies a dependency of type Xlogic. 7 | New, wire.Bind(new(Xlogic), new(*Service)), 8 | ) 9 | -------------------------------------------------------------------------------- /wire/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import "wire/repo" 4 | 5 | type Xlogic interface { 6 | GetEntity(id int) (*repo.Entity, error) 7 | } 8 | 9 | type Service struct { 10 | repo repo.Database 11 | } 12 | 13 | func New(r repo.Database) *Service { 14 | return &Service{repo: r} 15 | } 16 | 17 | func (s *Service) GetEntity(id int) (*repo.Entity, error) { 18 | entity, err := s.repo.GetEntity(id) 19 | if err != nil { 20 | return nil, err 21 | } 22 | 23 | // do something with entity... 24 | 25 | return entity, nil 26 | } 27 | -------------------------------------------------------------------------------- /wire/wire.go: -------------------------------------------------------------------------------- 1 | // +build wireinject 2 | 3 | package main 4 | 5 | import ( 6 | "database/sql" 7 | "net" 8 | "wire/repo" 9 | "wire/rpci" 10 | "wire/service" 11 | 12 | "github.com/google/wire" 13 | "google.golang.org/grpc" 14 | ) 15 | 16 | func NewListener() (net.Listener, error) { 17 | return net.Listen("tcp4", "0.0.0.0:5000") 18 | } 19 | 20 | func NewGRPCServer() *grpc.Server { 21 | return grpc.NewServer() 22 | } 23 | 24 | func DBConn() (*sql.DB, error) { 25 | return sql.Open("mysql", "127.0.0.1:3306") 26 | } 27 | 28 | func initApp() (*App, error) { 29 | wire.Build( 30 | rpci.New, 31 | NewListener, 32 | NewGRPCServer, 33 | repo.Provider, 34 | DBConn, 35 | service.Provider, 36 | wire.Struct(new(App), "*"), 37 | ) 38 | 39 | return &App{}, nil 40 | } 41 | -------------------------------------------------------------------------------- /wire/wire_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by Wire. DO NOT EDIT. 2 | 3 | //go:generate wire 4 | //+build !wireinject 5 | 6 | package main 7 | 8 | import ( 9 | "database/sql" 10 | "google.golang.org/grpc" 11 | "net" 12 | "wire/repo" 13 | "wire/rpci" 14 | "wire/service" 15 | ) 16 | 17 | // Injectors from wire.go: 18 | 19 | func initApp() (*App, error) { 20 | listener, err := NewListener() 21 | if err != nil { 22 | return nil, err 23 | } 24 | server := NewGRPCServer() 25 | db, err := DBConn() 26 | if err != nil { 27 | return nil, err 28 | } 29 | repoDB := repo.New(db) 30 | serviceService := service.New(repoDB) 31 | rpciServer := rpci.New(serviceService, server) 32 | app := &App{ 33 | listener: listener, 34 | gsrv: server, 35 | rpcImpl: rpciServer, 36 | } 37 | return app, nil 38 | } 39 | 40 | // wire.go: 41 | 42 | func NewListener() (net.Listener, error) { 43 | return net.Listen("tcp4", "0.0.0.0:5000") 44 | } 45 | 46 | func NewGRPCServer() *grpc.Server { 47 | return grpc.NewServer() 48 | } 49 | 50 | func DBConn() (*sql.DB, error) { 51 | return sql.Open("mysql", "127.0.0.1:3306") 52 | } 53 | --------------------------------------------------------------------------------