听着Stand by me 也不知道为啥就有感觉写了,开始写的时候都不知道取什么标题,本来是想记录一下在写rkgrpcwebproxy时候的一个方法,主要解决的是结构体默认参数的问题。有点类似类初始化的默认参数,但感觉又很不相同,这可能就是golang独特的东西吧。
其实还是代码比较能说明问题
先准备一个结构体,这里我用的是rkgrpcwebproxy里面的入口结构体
type GRPCWebEntry struct {
Name string `yaml:"name" json:"name"` #rk 注册的名称
Enabled bool `yaml:"enabled" json:"enabled"` #是否使用的开关
Description string `yaml:"description" json:"description"` #描述
Type string `yaml:"type" json:"type"` #rk 注册类型
LoggerEntry *rkentry.LoggerEntry `json:"-" yaml:"-"` # 可选的 rk log实例
GrpcEntry *rkgrpc.GrpcEntry `yaml:"-" json:"-"` # 可选的 rk grpc实例
CertEntry *rkentry.CertEntry `json:"-" yaml:"-"` # 可选的 rk证书实例
ServerAddress string `yaml:"serverAddress" json:"server_address"` #代理的gRPC服务地址 存在GrpcEntry的时候直接用实例的参数地址
BindAddress string `yaml:"bindAddress" json:"bind_address"` #代理绑定的IP 0.0.0.0
BindPort int `yaml:"bindPort" json:"bind_port"` #代理绑定端口 Port 8000
MaxCallRecvMsgSize int `yaml:"maxCallRecvMsgSize" json:"max_call_recv_msg_size"` #最大接受数据的大小 默认4M
AllowedOrigins []string `yaml:"allowedOrigins" json:"allowed_origins"` #允许访问域
AllowedHeaders []string `yaml:"allowedHeaders" json:"allowed_headers"` #允许的表头
Websockets *Websockets `yaml:"websockets" json:"websockets"`
Debug bool `yaml:"debug" json:"debug"` #是否调试
HttpMaxWriteTimeout time.Duration `yaml:"http_max_write_timeout" json:"http_max_write_timeout"` #http 最大写入时间
HttpMaxReadTimeout time.Duration `yaml:"http_max_read_timeout" json:"http_max_read_timeout"` #http 最大读取时间
}
这个结构体主要用途就是实例化 grpc web 代理,在注释中也能看出来,我们有很多的默认值和可选项,我开始学go的时候用的是New:
func NewGRPCWebEntry() *GRPCWebEntry {
return &GRPCWebEntry{
Debug: false, //默认值
}
}
这种方法是可以添加默认值的,碰见的问题就是不灵活,如果要改会造成很多的问题,改造一下:
func NewGRPCWebEntry(opts ...interface{}) *GRPCWebEntry {
entry := &GRPCWebEntry{
Debug: false,
}
for i, opt := range opts {
//在这里处理添加的参数
}
return entry
}
因为go是强类型的所以我们需要一个中间类型
func NewGRPCWebEntry(opts ...GRPCWebEntryOption) *GRPCWebEntry {
entry := &GRPCWebEntry{
Debug: false,
}
for i, opt := range opts {
//在这里处理添加的参数
}
return entry
}
type GRPCWebEntryOption func(*GRPCWebEntry)
最后就是水到渠成了
func NewGRPCWebEntry(opts ...GRPCWebEntryOption) *GRPCWebEntry {
entry := &GRPCWebEntry{
Debug: false, //默认调试为false
}
for i := range opts {
opts[i](entry)
}
return entry
}
type GRPCWebEntryOption func(*GRPCWebEntry)
//修改调试模式
func WithDebug(debug bool) GRPCWebEntryOption {
return func(entry *GRPCWebEntry) {
entry.Debug = debug
}
}
测试一下默认效果
func main() {
entry := NewGRPCWebEntry()
fmt.Println("entry debug", entry.Debug)
}
// Print : entry debug false
测试修改的效果
func main() {
entry := NewGRPCWebEntry(WithDebug(true))
fmt.Println("entry debug", entry.Debug)
}
// Print : entry debug true
其他的参数也能参照WithDebug来修改,这样实现灵活修改默认值的效果。
对了,最后应该推荐一下rk这个开源的项目,看好的项目源码还是学习最好的方法!