当前位置: 首页 > news >正文

做技术网站赚钱吗电商平台有哪些?

做技术网站赚钱吗,电商平台有哪些?,太原网站建设山西悉云科技,开设计公司要怎么规划文章目录 生成器模式生成器代码生成 本文用生成器模式作为例子,来演示如何用代码生成代码。 生成器模式 熟悉 Java 开发的同学都知道,lombok 有一个著名的注解 Builder ,只要加在类上面,就可以自动生成 Builder 模式的代码。如下…

文章目录

  • 生成器模式
  • 生成器代码生成

本文用生成器模式作为例子,来演示如何用代码生成代码。

生成器模式

熟悉 Java 开发的同学都知道,lombok 有一个著名的注解 @Builder ,只要加在类上面,就可以自动生成 Builder 模式的代码。如下所示:

@Builder
public class DetectionQuery {private String uniqueKey;private Long   startTime;private Long   endTime;
}

然后就可以这样使用:

return DetectionQuery.builder().uniqueKey(uniqueKey).startTime(startTime).endTime(endTime).build();

是不是很爽?

不过 Go 可没有这样好用的注解。Go 你得自己手写。假设我们要造一辆车,车有车身、引擎、座位、轮子。Go 的生成器模式的代码是这样子的:

package modelimport "fmt"type ChinaCar struct {Body   stringEngine stringSeats  []stringWheels []string
}func newChinaCar(body string, engine string, seats []string, wheels []string) *ChinaCar {return &ChinaCar{Body:   body,Engine: engine,Seats:  seats,Wheels: wheels,}
}type CarBuilder struct {body   stringengine stringseats  []stringwheels []string
}func ChinaCharBuilder() *CarBuilder {return &CarBuilder{}
}func (b *CarBuilder) Build() *ChinaCar {return newChinaCar(b.body, b.engine, b.seats, b.wheels)
}func (b *CarBuilder) Body(body string) *CarBuilder {b.body = bodyreturn b
}func (b *CarBuilder) Engine(engine string) *CarBuilder {b.engine = enginereturn b
}func (b *CarBuilder) Seats(seats []string) *CarBuilder {b.seats = seatsreturn b
}func (b *CarBuilder) Wheels(wheels []string) *CarBuilder {b.wheels = wheelsreturn b
}func main() {car := ChinaCharBuilder().Body("More advanced").Engine("Progressed").Seats([]string{"good", "nice"}).Wheels([]string{"solid", "smooth"}).Build()fmt.Printf("%+v", car)
}

生成器模式怎么写?遵循三步即可:

(1) 先构造一个对应的生成器,这个生成器与目标对象有一样的属性;

(2) 对于每一个属性,有一个方法设置属性,然后返回生成器的引用本身;

(3) 最后调用生成器的 Build 方法,这个方法会调用目标对象的构造器来生成目标对象。

为啥不直接调用目标对象的构造器,要这么拐弯抹角呢?因为生成器模式一般用于复杂对象的构造。这个复杂对象的每一个组件都需要逐步构造,比如每一个Set方法中,可能都有一些对于属性的校验或者其他业务逻辑,而不是简单的给属性赋值就行。必须等所有组件都正确构造完成后,才能返回一个可用的目标对象。像 CarBuilder 这种才算是生成器模式的合理使用。而 DetectionQuerybuilder 模式只是为了享受链式调用的畅感。

生成器代码生成

用代码生成代码?嗯,其实不算稀奇。代码也只是一种普通的可读文本而已。

模板是用于动态生成文本的常用技术。虽然看上去不算特别高明的方式,但也很管用。咱们使用 Go template 来实现它。

思路与实现
首先要分析,哪些是固定的文本,哪些是动态的文本。

红框框出来的都是动态文本。事实上,除了几个关键字和括号是静态的以外,其它基本都是动态生成的。这些文本通常是根据业务对象类型和业务对象的属性名及属性类型来推理出来的。
在这里插入图片描述

先根据最终要生成的代码,把模板文件给定义出来(这里可以用自然语言先填充,再替换成技术实现):

func New{{ 目标对象类型 }}(逗号分隔的属性名 属性类型列表)) *{{ 目标对象类型 }} {return &{{ 目标对象类型 }}{每一行都是:  属性名 :属性名 (属性名小写)}
}type {{ 生成器类型 }} struct {每一行都是:  属性名  属性类型(属性名小写)
}func {{ 生成器方法名 }}() *{{ 生成器类型 }} {return &{{ 生成器类型 }}{}
}func (b *{{ 生成器类型 }}) Build() *{{ 目标对象类型 }} {return New{{ 目标对象类型 }}(逗号分隔的  b.属性名 列表
}// 对于每一个属性,遍历,做如下动作:func (b *{{ 生成器类型 }}) {{ 属性名 }}({{ 属性名(小写) }} {{ 属性类型 }}) *{{ 生成器类型 }} {b.{{ 属性名(小写) }} = {{ 属性名(小写) }}return b
}

然后,抽象出用来填充动态文本的填充对象(即要传给模版的参数对象,存储了在模板中需要用的动态信息):

type BuilderInfo struct {BuilderMethod stringBuilderClass  stringBizClass      stringAttrs         []Attr
}type Attr struct {Name stringType string
}func newAttr(Name, Type string) Attr {return Attr{Name: Name, Type: Type}
}

接下来,要根据具体的模板语言,来填充上面的自然语言,同时从目标对象中生成填充对象,来填充这些动态文本和自定义函数。

如下代码所示:

builder_tpl 就是生成器模式的代码模板文本。我们先用具体的值填充,把模板调通,然后再把这些具体的值用函数替换。

func LowercaseFirst(s string) string {r, n := utf8.DecodeRuneInString(s)return string(unicode.ToLower(r)) + s[n:]
}func MapName(attrs []Attr) []string {return util.Map[Attr, string](attrs, func(attr Attr "Attr, string") string { return "b." + LowercaseFirst(attr.Name) })
}func MapNameAndType(attrs []Attr) []string {return util.Map[Attr, string](attrs, func(attr Attr "Attr, string") string { return LowercaseFirst(attr.Name) + " " + LowercaseFirst(attr.Type) })
}func autoGenBuilder(builder_tpl string) {t1 := template.Must(template.New("test").Funcs(template.FuncMap{"lowercaseFirst": LowercaseFirst, "join": strings.Join, "mapName": MapName, "mapNameAndType": MapNameAndType,}).Parse(builder_tpl))bi := BuilderInfo{BuilderMethod: "QueryBuilder",BuilderClass:  "CarBuilder",BizClass:      "ChinaCar",Attrs: []Attr{newAttr("Body", "string"), newAttr("Engine", "string"),newAttr("Seats", "[]string"), newAttr("Wheels", "[]string")},}t1.ExecuteTemplate(os.Stdout, "test", bi)
}func main() {builder_tpl := `func New{{ .BizClass }}({{- join (mapNameAndType .Attrs) ", " }})) *{{ .BizClass }} {return &{{ .BizClass }}{{{ range .Attrs }}{{ .Name }}:      {{ lowercaseFirst .Name }},{{ end }}}
}type {{ .BuilderClass }} struct {{{ range .Attrs }}{{ lowercaseFirst .Name }}   {{ .Type }}
{{ end }}
}func {{ .BuilderMethod }}() *{{ .BuilderClass }} {return &{{ .BuilderClass }}{}
}func (b *{{ .BuilderClass }}) Build() *{{ .BizClass }} {return New{{ .BizClass }}({{- join (mapName .Attrs) ", " }})
}{{- range .Attrs }}
func (b *{{ $.BuilderClass }}) {{ .Name }}({{ lowercaseFirst .Name }} {{ .Type }}) *{{ $.BuilderClass }} {b.{{ lowercaseFirst .Name }} = {{ lowercaseFirst .Name }}return b
}
{{- end }}`car := model.ChinaCar{}//autoGenBuilder(builder_tpl)autoGenBuilder2(builder_tpl, car)
}

这里基本上概括了Go template 的常用语法:

{{ . }} 表示顶层作用域对象,也就是你从如下方法传入的 bi 对象。
{{ .BuilderClass }} 就是取bi.BuilderClass , {{ .Attrs }} 就是取 bi.Attrs

t1.ExecuteTemplate(os.Stdout, "test", bi)

这有个 range 循环, 取 Attrs 里的每一个元素进行循环。注意到,range 里面的 {{ .Name }}.表示的是Attrs里的每一个元素对象。

  {{ range .Attrs }}{{ .Name }}:      {{ lowercaseFirst .Name }},{{ end }}

这里还传入了一个自定义函数 lowercaseFirst, 可以通过如下方法传入:

t1 := template.Must(template.New("test").Funcs(template.FuncMap{"lowercaseFirst": LowercaseFirst, "join": strings.Join, "mapName": MapName, "mapNameAndType": MapNameAndType,}).Parse(builder_tpl))

还有一个技巧,就是如何在 range 循环里引用顶层对象。这里要引用 BuilderClass 的值,必须用 $.BuilderClass,否则输出为空。

{{- range .Attrs }}
func (b *{{ $.BuilderClass }}) {{ .Name }}({{ lowercaseFirst .Name }} {{ .Type }}) *{{ $.BuilderClass }} {b.{{ lowercaseFirst .Name }} = {{ lowercaseFirst .Name }}return b
}
{{- end }}

嗯,多写写就熟了。通过实战来练习和掌握是一种高效学习之法。

注意一定要写 . 号。我最开始老是忘记写。然后就卡住没响应了。

go template 报错不太友好。分三种情况:

  • 直接卡住,你也不知道到底发生了什么。比如 {{ .BuilderClass }} 写成 {{ BuilderClass }}
  • 直接报错,地址引用错误。比如模板语法错误。
  • 不输出内容。比如引用不到内容。

进一步完善
接下来,就要把写死的 BuilderMethod, BuilderClass, BizClassAttrs通过给定的业务类型来生成。

func GetBizClass(t any) string {qualifiedClass := fmt.Sprintf("%T", t)return qualifiedClass[strings.Index(qualifiedClass, ".")+1:]
}func GetAttributes(obj any) []Attr {typ := reflect.TypeOf(obj)attrs := make([]Attr, typ.NumField())for i := 0; i < typ.NumField(); i++ {field := typ.Field(i)attr := Attr{Name: field.Name,Type: field.Type.String(),}attrs[i] = attr}return attrs
}

GetBizClass GetAttributes 生成的值分别填充那几处硬写的值即可。

程序的主体,本文已经都给出来了,读者也可以将其拼接起来,做一次完型填空。


文章转载自:
http://dinncorump.stkw.cn
http://dinncopaddy.stkw.cn
http://dinncopunch.stkw.cn
http://dinncosixteenthly.stkw.cn
http://dinncoanatine.stkw.cn
http://dinncooutgoing.stkw.cn
http://dinncoinhalatorium.stkw.cn
http://dinncobandhnu.stkw.cn
http://dinncozinco.stkw.cn
http://dinncoechovirus.stkw.cn
http://dinncoastoundment.stkw.cn
http://dinncomange.stkw.cn
http://dinncogally.stkw.cn
http://dinncopapeete.stkw.cn
http://dinncoplainspoken.stkw.cn
http://dinncoeroduction.stkw.cn
http://dinncogaleeny.stkw.cn
http://dinncocloistral.stkw.cn
http://dinncograndnephew.stkw.cn
http://dinncosiphonal.stkw.cn
http://dinncoplagiarize.stkw.cn
http://dinncomuricate.stkw.cn
http://dinncoextravagantly.stkw.cn
http://dinncoor.stkw.cn
http://dinncomunicipality.stkw.cn
http://dinncooiled.stkw.cn
http://dinncobenzomorphan.stkw.cn
http://dinncoheadspace.stkw.cn
http://dinncothrostle.stkw.cn
http://dinncoatypic.stkw.cn
http://dinncounderpin.stkw.cn
http://dinncoburgonet.stkw.cn
http://dinncoyellowtop.stkw.cn
http://dinncozoospermatic.stkw.cn
http://dinncoeroticize.stkw.cn
http://dinncostipe.stkw.cn
http://dinncoventriloquous.stkw.cn
http://dinncocytogenetic.stkw.cn
http://dinncopyjamas.stkw.cn
http://dinncoelectrosensory.stkw.cn
http://dinncohomy.stkw.cn
http://dinncoectozoic.stkw.cn
http://dinncohurtlingly.stkw.cn
http://dinncohermia.stkw.cn
http://dinncobushed.stkw.cn
http://dinnconopal.stkw.cn
http://dinncoest.stkw.cn
http://dinncoinframedian.stkw.cn
http://dinncocabretta.stkw.cn
http://dinncoquickwater.stkw.cn
http://dinncorooftree.stkw.cn
http://dinncohomozygously.stkw.cn
http://dinncoemergencies.stkw.cn
http://dinncolavatory.stkw.cn
http://dinncoshily.stkw.cn
http://dinncoromper.stkw.cn
http://dinncoroyally.stkw.cn
http://dinncodowner.stkw.cn
http://dinncopoove.stkw.cn
http://dinncomultiserver.stkw.cn
http://dinncoreceptionist.stkw.cn
http://dinncoskyward.stkw.cn
http://dinncoweltansicht.stkw.cn
http://dinncoflightism.stkw.cn
http://dinncoincorruptibly.stkw.cn
http://dinncoprimordial.stkw.cn
http://dinncobookkeeping.stkw.cn
http://dinncospleen.stkw.cn
http://dinncolintel.stkw.cn
http://dinncodrawling.stkw.cn
http://dinncoflirtation.stkw.cn
http://dinncomamaguy.stkw.cn
http://dinncoundistinguished.stkw.cn
http://dinncomonophyllous.stkw.cn
http://dinncotamber.stkw.cn
http://dinncoamateurish.stkw.cn
http://dinncoabigail.stkw.cn
http://dinncoinflective.stkw.cn
http://dinncotagalog.stkw.cn
http://dinncoalamein.stkw.cn
http://dinncopeaky.stkw.cn
http://dinncorideau.stkw.cn
http://dinncotelecommand.stkw.cn
http://dinncovinum.stkw.cn
http://dinncopaddock.stkw.cn
http://dinncoklavier.stkw.cn
http://dinncoexpansionary.stkw.cn
http://dinncosocker.stkw.cn
http://dinncocandour.stkw.cn
http://dinncopinitol.stkw.cn
http://dinncounminished.stkw.cn
http://dinncoupya.stkw.cn
http://dinncojdisplay.stkw.cn
http://dinncocaplin.stkw.cn
http://dinncopenninite.stkw.cn
http://dinncosuggestibility.stkw.cn
http://dinncodismember.stkw.cn
http://dinncosemaphoric.stkw.cn
http://dinncoinkiness.stkw.cn
http://dinncophotoplate.stkw.cn
http://www.dinnco.com/news/122901.html

相关文章:

  • wordpress建站案例seo排名系统
  • wordpress前端注册插件网站优化效果
  • 网站做语言切换沈阳seo排名优化教程
  • 只做鞋子的网站百度seo提高排名费用
  • 锦兴建筑人才招聘平台公众号排名优化
  • wordpress影视站主题长沙网站建设
  • 做电影网站哪个系统好网站域名购买
  • wordpress 解析插件合肥seo整站优化
  • 网站所有者查询南京网站推广公司
  • 专门做辅助的扎金花网站产品营销推广方案
  • 网站备案 换空间seo博客模板
  • 建网站找那家好seo内容优化
  • 网站建设公司武汉在线培训网站
  • 网站在线订单系统怎么做广州高端网站建设公司
  • 商务网站建设策划书范文web网址
  • 2013我国中小企业接入互联网和网站建设情况怎么查百度搜索排名
  • 广州 网站建设公司百度问一问付费咨询
  • 成都网站制作电话手机优化软件哪个好用
  • 首页调用网站栏目id如何做网络营销推广
  • 建设电商网站流程永久域名查询
  • 上海今天新闻综合频道百度seo有用吗
  • 网站建设业务范围企业内训机构
  • 怎样做加入购物车的网站百度seo白皮书
  • 阿里云域名申请注册重庆seo小潘大神
  • 外包加工网上可靠吗成都seo公司
  • wordpress产品图片大小不一seo整站优化新站快速排名
  • 网站模板怎么连接域名营销策略有哪些有效手段
  • 宁波网站建站模板附近哪里有计算机培训班
  • 做网站是否要备案sq网站推广
  • 武汉地区网站建设拼多多关键词排名查询软件