From cfe946b21903db9d77f144b6146a2b8f86240f06 Mon Sep 17 00:00:00 2001 From: chai2010 Date: Sat, 14 Jul 2018 23:03:45 +0800 Subject: [PATCH] =?UTF-8?q?ch4:=20=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ch4-rpc/ch4-05-grpc-hack.md | 19 ++- ch4-rpc/ch4-06-grpc-ext.md | 158 +++++++++++++++++- .../pb2-default-value/Makefile | 10 ++ .../pb2-default-value/helloworld.pb.go | 110 ++++++++++++ .../pb2-default-value/helloworld.proto | 15 ++ .../ch4-06-grpc-ext/validators/Makefile | 14 ++ .../validators/helloworld.pb.go | 88 ++++++++++ .../validators/helloworld.proto | 10 ++ .../validators/helloworld.validator.pb.go | 40 +++++ .../http-router/dummy.txt | 0 .../pb-option/dummy.txt | 0 .../pb-web-frameswork/dummy.txt | 0 .../plugin-framework/dummy.txt | 0 13 files changed, 458 insertions(+), 6 deletions(-) create mode 100644 vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/Makefile create mode 100644 vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/helloworld.pb.go create mode 100644 vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/helloworld.proto create mode 100644 vendor/gobook.examples/ch4-06-grpc-ext/validators/Makefile create mode 100644 vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.pb.go create mode 100644 vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.proto create mode 100644 vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.validator.pb.go rename vendor/gobook.examples/{ch4-06-pb => ch4-07-pb}/http-router/dummy.txt (100%) rename vendor/gobook.examples/{ch4-06-pb => ch4-07-pb}/pb-option/dummy.txt (100%) rename vendor/gobook.examples/{ch4-06-pb => ch4-07-pb}/pb-web-frameswork/dummy.txt (100%) rename vendor/gobook.examples/{ch4-06-pb => ch4-07-pb}/plugin-framework/dummy.txt (100%) diff --git a/ch4-rpc/ch4-05-grpc-hack.md b/ch4-rpc/ch4-05-grpc-hack.md index 0ac33dc..d53b6e3 100644 --- a/ch4-rpc/ch4-05-grpc-hack.md +++ b/ch4-rpc/ch4-05-grpc-hack.md @@ -314,7 +314,24 @@ func filter( } ``` -不够GRPC框架中只能为每个服务设置一个截取器,因此所有对截取工作只能在一个函数中完成。不过开源的grpc-ecosystem项目中的go-grpc-middleware包已经基于GRPC对截取器实现了链式截取器的支持,感兴趣的同学可以参考。 +不够GRPC框架中只能为每个服务设置一个截取器,因此所有对截取工作只能在一个函数中完成。开源的grpc-ecosystem项目中的go-grpc-middleware包已经基于GRPC对截取器实现了链式截取器的支持。 + +以下是go-grpc-middleware包中链式截取器的简单用法 + +```go +import "github.com/grpc-ecosystem/go-grpc-middleware" + +myServer := grpc.NewServer( + grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( + filter1, filter2, ... + )), + grpc.StreamInterceptor(grpc_middleware.ChainStreamServer( + filter1, filter2, ... + )), +) +``` + +感兴趣的同学可以参考go-grpc-middleware包的代码。 ## 和Web服务共存 diff --git a/ch4-rpc/ch4-06-grpc-ext.md b/ch4-rpc/ch4-06-grpc-ext.md index df4ef8a..80fd98f 100644 --- a/ch4-rpc/ch4-06-grpc-ext.md +++ b/ch4-rpc/ch4-06-grpc-ext.md @@ -1,9 +1,157 @@ # 4.6. GRPC扩展 - +目前开源社区已经围绕Protobuf和GRPC开发出众多扩展,形成了庞大的生态。本节我们将简单介绍验证器、REST接口和Nginx代理等几个比较流行的扩展。 + +## 验证器 + +到目前位置,我们接触的全部是第三版的Protobuf语法。第二版的Protobuf有个默认值特性,可以为字符串或数值类型的成员定义默认值。 + +我们采用第二版的Protobuf语法创建文件: + +```protobuf +syntax = "proto2"; + +package main; + +message Message { + optional string name = 1 [default = "gopher"]; + optional int32 age = 2 [default = 10]; +} +``` + +默认值语法内置其实是通过Protobuf的扩展选项特性实现。在第三版的Protobuf中不再支持默认值特性,但是我们可以通过扩展选项自己定制默认值。 + +下面是用proto3语法的扩展特性重新改写上述的proto文件: + +```protobuf +syntax = "proto3"; + +package main; + +import "google/protobuf/descriptor.proto"; + +extend google.protobuf.FieldOptions { + string default_string = 50000; + int32 default_int = 50001; +} + +message Message { + string name = 1 [(default_string) = "gopher"]; + int32 age = 2[(default_int) = 10]; +} +``` + +其中成员后面的方括号内部的就是扩展语法。重新生成Go语言代码,里面会包含扩展选项相关的元信息: + +```go +var E_DefaultString = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.FieldOptions)(nil), + ExtensionType: (*string)(nil), + Field: 50000, + Name: "main.default_string", + Tag: "bytes,50000,opt,name=default_string,json=defaultString", + Filename: "helloworld.proto", +} + +var E_DefaultInt = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.FieldOptions)(nil), + ExtensionType: (*int32)(nil), + Field: 50001, + Name: "main.default_int", + Tag: "varint,50001,opt,name=default_int,json=defaultInt", + Filename: "helloworld.proto", +} +``` + +我们可以在运行时通过类似反射的技术解析出Message每个成员定义的扩展选项,然后从每个扩展的相关联的信息中解析出我们定义的默认值。 + +在开源社区中,github.com/mwitkow/go-proto-validators 基于Protobuf的扩展特性实现了功能较为强大的验证器功能。要使用该验证器首先需要下载其提供的代码生成插件: + +``` +$ go get github.com/mwitkow/go-proto-validators/protoc-gen-govalidators +``` + +然后基于go-proto-validators验证器重新定义上述的Message成员的验证规则: + +```protobuf +syntax = "proto3"; + +package main; + +import "github.com/mwitkow/go-proto-validators/validator.proto"; + +message Message { + string important_string = 1 [(validator.field) = {regex: "^[a-z]{2,5}$"}]; + int32 age = 2 [(validator.field) = {int_gt: 0, int_lt: 100}]; +} +``` + +在方括弧表示的成员扩展中,validator.field表示扩展是validator包中定义的名为field扩展选项。validator.field的类型是FieldValidator结构体,在导入的validator.proto文件中定义。 + +validator.proto文件的内容如下: + +```protobuf +syntax = "proto2"; +package validator; + +import "google/protobuf/descriptor.proto"; + +extend google.protobuf.FieldOptions { + optional FieldValidator field = 65020; +} + +message FieldValidator { + // Uses a Golang RE2-syntax regex to match the field contents. + optional string regex = 1; + // Field value of integer strictly greater than this value. + optional int64 int_gt = 2; + // Field value of integer strictly smaller than this value. + optional int64 int_lt = 3; + + // ... more ... +} +``` + +从FieldValidator定义的注释中我们可以知道验证器扩展的一些语法:其中regex表示用于字符串验证的正则表达式,int_gt和int_lt表示数值的范围。 + +采用以下的命令生成验证函数代码: + +``` +protoc \ + --proto_path=${GOPATH}/src \ + --proto_path=${GOPATH}/src/github.com/google/protobuf/src \ + --proto_path=. \ + --govalidators_out=. \ + hello.proto +``` + +以上的命令会调用protoc-gen-govalidators程序,生成一个名为hello.validator.pb.go的代码: + +```go +var _regex_Message_ImportantString = regexp.MustCompile("^[a-z]{2,5}$") + +func (this *Message) Validate() error { + if !_regex_Message_ImportantString.MatchString(this.ImportantString) { + return go_proto_validators.FieldError("ImportantString", fmt.Errorf(`value '%v' must be a string conforming to regex "^[a-z]{2,5}$"`, this.ImportantString)) + } + if !(this.Age > 0) { + return go_proto_validators.FieldError("Age", fmt.Errorf(`value '%v' must be greater than '0'`, this.Age)) + } + if !(this.Age < 100) { + return go_proto_validators.FieldError("Age", fmt.Errorf(`value '%v' must be less than '100'`, this.Age)) + } + return nil +} +``` + +也就是为Message结构体增加了一个Validate方法,用于验证该成员是否满足Protobuf中定义的条件约束。 + +通过生成的验证函数,并结合GRPC的截取器,我们可以很容易为每个方法的输入参数和返回值进行验证。 + +## REST接口 + +TODO + +## Nginx代理 TODO diff --git a/vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/Makefile b/vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/Makefile new file mode 100644 index 0000000..331d98b --- /dev/null +++ b/vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/Makefile @@ -0,0 +1,10 @@ + +run: + @go build -o a.out && ./a.out + -@rm ./a.out + +gen: + protoc -I . --go_out=plugins=grpc:. helloworld.proto + +clean: + -rm *.pb.go diff --git a/vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/helloworld.pb.go b/vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/helloworld.pb.go new file mode 100644 index 0000000..98a98a1 --- /dev/null +++ b/vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/helloworld.pb.go @@ -0,0 +1,110 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: helloworld.proto + +package main + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Message struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Age int32 `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_helloworld_0196a2ef510324e3, []int{0} +} +func (m *Message) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Message.Unmarshal(m, b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Message.Marshal(b, m, deterministic) +} +func (dst *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(dst, src) +} +func (m *Message) XXX_Size() int { + return xxx_messageInfo_Message.Size(m) +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +func (m *Message) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Message) GetAge() int32 { + if m != nil { + return m.Age + } + return 0 +} + +var E_DefaultString = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.FieldOptions)(nil), + ExtensionType: (*string)(nil), + Field: 50000, + Name: "main.default_string", + Tag: "bytes,50000,opt,name=default_string,json=defaultString", + Filename: "helloworld.proto", +} + +var E_DefaultInt = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.FieldOptions)(nil), + ExtensionType: (*int32)(nil), + Field: 50001, + Name: "main.default_int", + Tag: "varint,50001,opt,name=default_int,json=defaultInt", + Filename: "helloworld.proto", +} + +func init() { + proto.RegisterType((*Message)(nil), "main.Message") + proto.RegisterExtension(E_DefaultString) + proto.RegisterExtension(E_DefaultInt) +} + +func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_helloworld_0196a2ef510324e3) } + +var fileDescriptor_helloworld_0196a2ef510324e3 = []byte{ + // 217 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, + 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xc9, 0x4d, + 0xcc, 0xcc, 0x93, 0x52, 0x48, 0xcf, 0xcf, 0x4f, 0xcf, 0x49, 0xd5, 0x07, 0x8b, 0x25, 0x95, 0xa6, + 0xe9, 0xa7, 0xa4, 0x16, 0x27, 0x17, 0x65, 0x16, 0x94, 0xe4, 0x17, 0x41, 0xd4, 0x29, 0x39, 0x72, + 0xb1, 0xfb, 0xa6, 0x16, 0x17, 0x27, 0xa6, 0xa7, 0x0a, 0xc9, 0x71, 0xb1, 0xe4, 0x25, 0xe6, 0xa6, + 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x3a, 0x71, 0x35, 0x6d, 0x95, 0x60, 0x4b, 0xcf, 0x2f, 0xc8, + 0x48, 0x2d, 0x0a, 0x02, 0x8b, 0x0b, 0x89, 0x71, 0x31, 0x27, 0xa6, 0xa7, 0x4a, 0x30, 0x29, 0x30, + 0x6a, 0xb0, 0x3a, 0xb1, 0x74, 0x6c, 0x95, 0xe0, 0x0a, 0x02, 0x09, 0x58, 0xb9, 0x71, 0xf1, 0xa5, + 0xa4, 0xa6, 0x25, 0x96, 0xe6, 0x94, 0xc4, 0x17, 0x97, 0x14, 0x65, 0xe6, 0xa5, 0x0b, 0xc9, 0xea, + 0x41, 0xec, 0xd5, 0x83, 0xd9, 0xab, 0xe7, 0x96, 0x99, 0x9a, 0x93, 0xe2, 0x5f, 0x50, 0x92, 0x99, + 0x9f, 0x57, 0x2c, 0x71, 0xa1, 0x8d, 0x19, 0x64, 0x45, 0x10, 0x2f, 0x54, 0x5b, 0x30, 0x58, 0x97, + 0x95, 0x03, 0x17, 0x37, 0xcc, 0x9c, 0xcc, 0xbc, 0x12, 0x42, 0x86, 0x5c, 0x04, 0x1b, 0xc2, 0x1a, + 0xc4, 0x05, 0xd5, 0xe3, 0x99, 0x57, 0x92, 0xc4, 0x06, 0x56, 0x6a, 0x0c, 0x08, 0x00, 0x00, 0xff, + 0xff, 0xce, 0x8c, 0x0b, 0x48, 0x0f, 0x01, 0x00, 0x00, +} diff --git a/vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/helloworld.proto b/vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/helloworld.proto new file mode 100644 index 0000000..04fa1c0 --- /dev/null +++ b/vendor/gobook.examples/ch4-06-grpc-ext/pb2-default-value/helloworld.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package main; + +import "google/protobuf/descriptor.proto"; + +extend google.protobuf.FieldOptions { + string default_string = 50000; + int32 default_int = 50001; +} + +message Message { + string name = 1 [(default_string) = "gopher"]; + int32 age = 2[(default_int) = 10]; +} diff --git a/vendor/gobook.examples/ch4-06-grpc-ext/validators/Makefile b/vendor/gobook.examples/ch4-06-grpc-ext/validators/Makefile new file mode 100644 index 0000000..c556d58 --- /dev/null +++ b/vendor/gobook.examples/ch4-06-grpc-ext/validators/Makefile @@ -0,0 +1,14 @@ + +run: + @go build -o a.out && ./a.out + -@rm ./a.out + +aa: + cd ../../.. && pwd + +gen: + protoc -I=. -I=../../.. --go_out=plugins=grpc:. helloworld.proto + protoc -I=. -I=../../.. --govalidators_out=. helloworld.proto + +clean: + -rm *.pb.go diff --git a/vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.pb.go b/vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.pb.go new file mode 100644 index 0000000..d4dd865 --- /dev/null +++ b/vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.pb.go @@ -0,0 +1,88 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: helloworld.proto + +package main + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/mwitkow/go-proto-validators" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Message struct { + ImportantString string `protobuf:"bytes,1,opt,name=important_string,json=importantString,proto3" json:"important_string,omitempty"` + Age int32 `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_helloworld_6a5a39a6dbe7620e, []int{0} +} +func (m *Message) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Message.Unmarshal(m, b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Message.Marshal(b, m, deterministic) +} +func (dst *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(dst, src) +} +func (m *Message) XXX_Size() int { + return xxx_messageInfo_Message.Size(m) +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +func (m *Message) GetImportantString() string { + if m != nil { + return m.ImportantString + } + return "" +} + +func (m *Message) GetAge() int32 { + if m != nil { + return m.Age + } + return 0 +} + +func init() { + proto.RegisterType((*Message)(nil), "main.Message") +} + +func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_helloworld_6a5a39a6dbe7620e) } + +var fileDescriptor_helloworld_6a5a39a6dbe7620e = []byte{ + // 185 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, + 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xc9, 0x4d, + 0xcc, 0xcc, 0x93, 0x32, 0x4b, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0xcf, + 0x2d, 0xcf, 0x2c, 0xc9, 0xce, 0x2f, 0xd7, 0x4f, 0xcf, 0xd7, 0x05, 0x2b, 0xd1, 0x2d, 0x4b, 0xcc, + 0xc9, 0x4c, 0x49, 0x2c, 0xc9, 0x2f, 0x2a, 0xd6, 0x87, 0x33, 0x21, 0xba, 0x95, 0x52, 0xb8, 0xd8, + 0x7d, 0x53, 0x8b, 0x8b, 0x13, 0xd3, 0x53, 0x85, 0x6c, 0xb9, 0x04, 0x32, 0x73, 0x0b, 0xf2, 0x8b, + 0x4a, 0x12, 0xf3, 0x4a, 0xe2, 0x8b, 0x4b, 0x8a, 0x32, 0xf3, 0xd2, 0x25, 0x18, 0x15, 0x18, 0x35, + 0x38, 0x9d, 0x84, 0x1e, 0xdd, 0x97, 0xe7, 0xe3, 0xe2, 0x89, 0x8b, 0x4e, 0xd4, 0xad, 0x8a, 0xad, + 0x36, 0xd2, 0x31, 0xad, 0x55, 0x09, 0xe2, 0x87, 0xab, 0x0d, 0x06, 0x2b, 0x15, 0x92, 0xe2, 0x62, + 0x4e, 0x4c, 0x4f, 0x95, 0x60, 0x52, 0x60, 0xd4, 0x60, 0x75, 0xe2, 0x78, 0x74, 0x5f, 0x9e, 0x45, + 0x80, 0x41, 0x22, 0x25, 0x08, 0x24, 0x98, 0xc4, 0x06, 0xb6, 0xcc, 0x18, 0x10, 0x00, 0x00, 0xff, + 0xff, 0xa7, 0x15, 0x2e, 0x91, 0xbe, 0x00, 0x00, 0x00, +} diff --git a/vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.proto b/vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.proto new file mode 100644 index 0000000..4c97782 --- /dev/null +++ b/vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package main; + +import "github.com/mwitkow/go-proto-validators/validator.proto"; + +message Message { + string important_string = 1 [(validator.field) = {regex: "^[a-z]{2,5}$"}]; + int32 age = 2 [(validator.field) = {int_gt: 0, int_lt: 100}]; +} diff --git a/vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.validator.pb.go b/vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.validator.pb.go new file mode 100644 index 0000000..26649c1 --- /dev/null +++ b/vendor/gobook.examples/ch4-06-grpc-ext/validators/helloworld.validator.pb.go @@ -0,0 +1,40 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: helloworld.proto + +/* +Package main is a generated protocol buffer package. + +It is generated from these files: + helloworld.proto + +It has these top-level messages: + Message +*/ +package main + +import regexp "regexp" +import fmt "fmt" +import go_proto_validators "github.com/mwitkow/go-proto-validators" +import proto "github.com/golang/protobuf/proto" +import math "math" +import _ "github.com/mwitkow/go-proto-validators" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +var _regex_Message_ImportantString = regexp.MustCompile("^[a-z]{2,5}$") + +func (this *Message) Validate() error { + if !_regex_Message_ImportantString.MatchString(this.ImportantString) { + return go_proto_validators.FieldError("ImportantString", fmt.Errorf(`value '%v' must be a string conforming to regex "^[a-z]{2,5}$"`, this.ImportantString)) + } + if !(this.Age > 0) { + return go_proto_validators.FieldError("Age", fmt.Errorf(`value '%v' must be greater than '0'`, this.Age)) + } + if !(this.Age < 100) { + return go_proto_validators.FieldError("Age", fmt.Errorf(`value '%v' must be less than '100'`, this.Age)) + } + return nil +} diff --git a/vendor/gobook.examples/ch4-06-pb/http-router/dummy.txt b/vendor/gobook.examples/ch4-07-pb/http-router/dummy.txt similarity index 100% rename from vendor/gobook.examples/ch4-06-pb/http-router/dummy.txt rename to vendor/gobook.examples/ch4-07-pb/http-router/dummy.txt diff --git a/vendor/gobook.examples/ch4-06-pb/pb-option/dummy.txt b/vendor/gobook.examples/ch4-07-pb/pb-option/dummy.txt similarity index 100% rename from vendor/gobook.examples/ch4-06-pb/pb-option/dummy.txt rename to vendor/gobook.examples/ch4-07-pb/pb-option/dummy.txt diff --git a/vendor/gobook.examples/ch4-06-pb/pb-web-frameswork/dummy.txt b/vendor/gobook.examples/ch4-07-pb/pb-web-frameswork/dummy.txt similarity index 100% rename from vendor/gobook.examples/ch4-06-pb/pb-web-frameswork/dummy.txt rename to vendor/gobook.examples/ch4-07-pb/pb-web-frameswork/dummy.txt diff --git a/vendor/gobook.examples/ch4-06-pb/plugin-framework/dummy.txt b/vendor/gobook.examples/ch4-07-pb/plugin-framework/dummy.txt similarity index 100% rename from vendor/gobook.examples/ch4-06-pb/plugin-framework/dummy.txt rename to vendor/gobook.examples/ch4-07-pb/plugin-framework/dummy.txt