您当前的位置:首页 > 淘宝百科

name的音标,name的音标怎么写(微服务:程序容器)

时间:2023-03-06 19:40:36

关于【name的音标】,name的音标怎么写,今天犇涌小编给您分享一下,如果对您有所帮助别忘了关注本站哦。

内容导航:1、清晰架构的 Go 微服务:程序容器2、name的音标怎么写

1、清晰架构的 Go 微服务:程序容器

name的音标,name的音标怎么写(微服务:程序容器)

作者 | 倚天码农

来源 | CSDN博客,责编 | 夕颜

出品 | CSDN(ID:CSDNnews)

清晰架构(Clean Architecture)的一个理念是隔离程序的框架,使框架不会接管你的应用程序,而是由你决定何时何地使用它们。在本程序中,我特意不在开始时使用任何框架,因此我可以更好地控制程序结构。只有在整个程序结构布局完成之后,我才会考虑用某些库替换本程序的某些组件。这样,引入的框架或第三方库的影响就会被正确的依赖关系所隔离。目前,除了logger,数据库,gRPC和Protobuf(这是无法避免的)之外,我只使用了两个第三方库ozzo-validation¹和YAML²,而其他所有库都是Go的标准库。

你可以使用本程序作为构建应用程序的基础。你可能会问,那么本框架岂不是要接管整个应用程序吗?是的。但事实是,无论是你自建框架还是引进第三方框架,你都需要一个基本框架作为构建应用程序的基础。该基础需要具有正确的依赖性和可靠的设计,然后你可以决定是否引入其他库。你当然可以自己建立一个框架,但你最终可能会花费大量的时间和精力来完善它。你也可以使用本程序作为起点,而不是构建自己的项目,从而为你节省时间和精力。

程序容器是项目中最复杂的部分,是将应用程序的不同部分粘合在一起的关键组件。本程序的其他部分是直截了当且易于理解的,但这一部分不是。好消息是,一旦你理解了这一部分,那么整个程序就都在掌控之中。

name的音标,name的音标怎么写(微服务:程序容器)

容器包(“container” package)的组成部分

容器包由五部分组成:

1.“容器”(“container”)包:它负责创建具体类型并将它们注入其他文件。顶级包中只有一个文件“container.go”,它定义容器的接口。

name的音标,name的音标怎么写(微服务:程序容器)

2.“servicecontainer”子包:容器接口的实现。只有一个文件“serviceContainer.go”,这是“容器”包的关键。以下是代码。它的起点是“InitApp”,它从文件中读取配置数据并设置日志记录器(logger)。

type ServiceContainer struct { FactoryMap map[string]interface{} AppConfig *config.AppConfig}func (sc *ServiceContainer) InitApp(filename string) error { var err error config, err := loadConfig(filename) if err != nil { return errors.Wrap(err, "loadConfig")} sc.AppConfig = config err = loadLogger(config.Log) if err != nil { return errors.Wrap(err, "loadLogger")} return nil}// loads the loggerfunc loadLogger(lc config.LogConfig) error { loggerType := lc.Code err := logFactory.GetLogFactoryBuilder(loggerType).Build(&lc) if err != nil { return errors.Wrap(err, "")} return nil}// loads the application configurationsfunc loadConfig(filename string) (*config.AppConfig, error) { ac, err := config.ReadConfig(filename) if err != nil { return nil, errors.Wrap(err, "read container")} return ac, nil}

3. “configs”子包:负责从YAML文件加载程序配置,并将它们保存到“appConfig”结构中以供容器使用。

name的音标,name的音标怎么写(微服务:程序容器)

4. “logger”子包:它里面只有一个文件“logger.go”,它提供了日志记录器接口和一个“Log”变量来访问日志记录器。因为每个文件都需要依赖记录,所以它需要一个独立的包来避免循环依赖。

name的音标,name的音标怎么写(微服务:程序容器)

5. 最后一部分是不同类型的工厂(factory)。

它的内部分层与应用层分层相匹配。对于“usecase”和“dataservice”层,有“usecasefactory”和“dataservicefactory”。另一个工厂是“datastorefactory”,它负责创建底层数据处理链接。因为数据提供者可以是gRPC或除数据库之外的其他类型的服务,所以它被称为“datastorefactry”而不是“databasefactory”。日志记录组件(logger)也有自己的工厂。

name的音标,name的音标怎么写(微服务:程序容器)

用例工厂(Use Case Factory)

对于每个用例,例如“registration”,接口在“usecase”包中定义,但具体类型在“usecase”包下的“registration”子包中定义。此外,容器包中有一个对应的工厂负责创建具体的用例实例。对于“注册(registration)”用例,它是“registrationFactory.go”。用例与用例工厂之间的关系是一对一的。用例工厂负责创建此用例的具体类型(concrete type)并调用其他工厂来创建具体类型所需的成员(member in a struct)。最低级别的具体类型是sql.DBs和gRPC连接,它们需要被传递给持久层,这样才能访问数据库中的数据。

如果Go支持泛型,你可以创建一个通用工厂来构建不同类型的实例。现在,我必须为每一层创建一个工厂。另一个选择是使用反射(refection),但它有不少问题,因此我没有采用。

“Registration” 用例工厂(Use Case Factory):

每次调用工厂时,它都会构建一个新类型。以下是“注册(Registration)”用例创建具体类型的代码。它是工厂方法模式(factory method pattern)的典型实现。如果你想了解有关如何在Go中实现工厂方法模式的更多信息,请参阅此处³.

// Build creates concrete type for RegistrationUseCaseInterfacefunc (rf *RegistrationFactory) Build(c container.Container, appConfig *config.AppConfig, key string) (UseCaseInterface, error) {uc := appConfig.UseCase.Registrationudi, err := buildUserData(c, &uc.UserDataConfig)if err != nil {return nil, errors.Wrap(err, "")}tdi, err := buildTxData(c, &uc.TxDataConfig)if err != nil {return nil, errors.Wrap(err, "")}ruc := registration.RegistrationUseCase{UserDataInterface: udi, TxDataInterface: tdi}return &ruc, nil}func buildUserData(c container.Container, dc *config.DataConfig) (dataservice.UserDataInterface, error) {dsi, err := dataservicefactory.GetDataServiceFb(dc.Code).Build(c, dc)if err != nil {return nil, errors.Wrap(err, "")}udi := dsi.(dataservice.UserDataInterface)return udi, nil}

数据存储工厂(Data store factory):

“注册(Registration)”用例需要通过数据存储工厂创建的数据库链接来访问数据库。所有代码都在“datastorefactory”子包中。我详细解释了数据存储工厂如何工作,请看这篇文章依赖注入(Dependency Injection)。

数据存储工厂的当前实现支持两个数据库和一个微服务,MySql和CouchDB,以及gRPC缓存服务; 每个实现都有自己的工厂文件。如果引入了新数据库,你只需添加一个新的工厂文件,并在以下代码中的“dsFbMap”中添加一个条目。

// To map "database code" to "database interface builder"// Concreate builder is in corresponding factory file. For example, "sqlFactory" is in "sqlFactory".govar dsFbMap = map[string]dsFbInterface{config.SQLDB: &sqlFactory{},config.COUCHDB: &couchdbFactory{},config.CACHE_GRPC: &cacheGrpcFactory{},}// DataStoreInterface serve as a marker to indicate the return type for Build methodtype DataStoreInterface interface{}// The builder interface for factory method pattern// Every factory needs to implement Build methodtype dsFbInterface interface {Build(container.Container, *config.DataStoreConfig) (DataStoreInterface, error)}//GetDataStoreFb is accessors for factoryBuilderMapfunc GetDataStoreFb(key string) dsFbInterface {return dsFbMap[key]}

以下是MySql数据库工厂的代码,它实现了上面的代码中定义的“dsFbInterface”。它创建了MySql数据库链接。

容器内部有一个注册表(registry),用作数据存储工厂创建的链接(如DB或gRPC连接)的缓存,它们在整个应用程序创建一次。无论何时需要它们,需首先从注册表中检索它,如果没有找到,则创建一个新的并将其放入注册表中。以下是“Build”代码。

// sqlFactory is receiver for Build methodtype sqlFactory struct{}// implement Build method for SQL databasefunc (sf *sqlFactory) Build(c container.Container, dsc *config.DataStoreConfig) (DataStoreInterface, error) {key := dsc.Code//if it is already in container, returnif value, found := c.Get(key); found {sdb := value.(*sql.DB)sdt := databasehandler.SqlDBTx{DB: sdb}logger.Log.Debug("found db in container for key:", key)return &sdt, nil}db, err := sql.Open(dsc.DriverName, dsc.UrlAddress)if err != nil {return nil, errors.Wrap(err, "")}// check the connectionerr = db.Pingif err != nil {return nil, errors.Wrap(err, "")}dt := databasehandler.SqlDBTx{DB: db}c.Put(key, db)return &dt, nil}

Grpc Factory:

对于“listUser”用例,它需要调用gRPC微服务(缓存服务),而创建它的工厂是“cacheFactory.go”。目前,数据服务的所有链接都是由数据存储工厂创建的。以下是gRPC工厂的代码。“Build”方法与“SqlFactory”的非常相似。

// DataStoreInterface serve as a marker to indicate the return type for Build methodtype DataStoreInterface interface{}// cacheGrpcFactory is an empty receiver for Build methodtype cacheGrpcFactory struct{}func (cgf *cacheGrpcFactory) Build(c container.Container, dsc *config.DataStoreConfig) (DataStoreInterface, error) {key := dsc.Code//if it is already in container, returnif value, found := c.Get(key); found {return value.(*grpc.ClientConn), nil}//not in map, need to create onelogger.Log.Debug("doesn't find cacheGrpc key=%v need to created a new one\n", key)conn, err := grpc.Dial(dsc.UrlAddress, grpc.WithInsecure)if err != nil {return nil, errors.Wrap(err, "")}c.Put(key, conn)return conn, err}

Logger factory:

Logger有自己的子包名为“loggerfactory”,其结构与“datastorefactory”子包非常相似。“logFactory.go”定义了日志记录器工厂构建器接口(builder interface)和映射(map)。每个单独的日志记录器都有自己的工厂文件。以下是日志工厂的代码:

// logger mapp to map logger code to logger buildervar logfactoryBuilderMap = map[string]logFbInterface{config.ZAP: &ZapFactory{},config.LOGRUS: &LogrusFactory{},}// interface for logger factorytype logFbInterface interface {Build(*config.LogConfig) error}// accessors for factoryBuilderMapfunc GetLogFactoryBuilder(key string) logFbInterface {return logfactoryBuilderMap[key]}

以下是ZAP工厂的代码。它类似于数据存储工厂。只有一个区别。由于记录器创建功能仅被调用一次,因此不需要注册表。

// receiver for zap factorytype ZapFactory struct{}// build zap loggerfunc (mf *ZapFactory) Build(lc *config.LogConfig) error {err := zap.RegisterLog(*lc)if err != nil {return errors.Wrap(err, "")}return nil}name的音标,name的音标怎么写(微服务:程序容器)

配置文件

配置文件使你可以全面了解程序的整体结构:

name的音标,name的音标怎么写(微服务:程序容器)

上图显示了文件的前半部分。第一部分是它支持的数据库配置; 第二部分是带有gRPC的微服务; 第三部分是它支持的日志记录器; 第四部分是本程序在运行时使用的日志记录器。

下图显示了文件的后半部分。它列出了应用程序的所有用例以及每个用例所需的数据服务。

name的音标,name的音标怎么写(微服务:程序容器)name的音标,name的音标怎么写(微服务:程序容器)

配置文件中应保存哪些数据?

不同的组件具有不同的配置项,一些组件可能具有许多配置项,例如日志记录器。我们不需要在配置文件中保存所有配置项,这可能使其太大而无法管理。通常我们只需要保存需要在运行时更改的选项或者可以在不同环境中(dev, prod, qa)值不同的选项。

name的音标,name的音标怎么写(微服务:程序容器)

设计是如何进化的?

容器包里似乎有太多东西,问题是我们是否需要所有这些?如果你不需要所有功能,我们当然可以简化它。当我开始创建它时,它非常简单,我不断添加功能,最终它才越来越复杂。

最开始时,我只是想使用工厂方法模式来创建具体类型,没有日志记录,没有配置文件,没有注册表。

我从用例和数据存储工厂开始。最初,对于每个用例,都会创建一个新的数据库链接,这并不理想。因此,我添加了一个注册表来缓存所有连接,以确保它们只创建一次。

然后我发现(我从这里获得了一些灵感⁵)将所有配置信息放在一个文件中进行集中管理是个好主意,这样我就可以在不改变代码的情况下进行更改。

我创建了一个YAML文件(appConfig [type] .yaml)和“appConfig.go”来将文件中的内容加载到应用程序配置结构(struct) - “appConfig”中并将其传递给工厂构建器(factory builder)。“[type]”可以是“prod”,“dev”,“test”等。配置文件只加载一次。目前,它没有使用任何第三方库,但我想将来切换到Vipe⁶,因为它可以支持从配置服务器中动态重新加载程序配置。要切换到Vipe,我只需要更改一个文件“appConfig.go”。

对于日志记录,整个程序我只想要一个logger实例,这样我就可以为整个程序设置相同的日志配置。我在容器内创建了一个日志记录器包。我还尝试了不同的日志库来确定哪一个是最好的,然后我创建了一个日志工厂,以便将来更容易添加新的日志记录器。有关详细信息,请阅读日志管理⁷。

完整的源程序链接 Github: https://github.com/jfeng45/servicetmpl

索引:

[1] ozzo-validation

[2] YAML support for the Go language

[3]Golang Factory Method

[4]Go Microservice with Clean Architecture: Dependency Injection

[5] How I pass around shared resources (databases, configuration, etc) within Golang projects

[6]viper

[7]Go Microservice with Clean Architecture: Application Logging

不堆砌术语,不罗列架构,不迷信权威,不盲从流行,坚持独立思考!

原文链接:

https://blog.csdn.net/weixin_38748858/article/details/103914642

name的音标,name的音标怎么写(微服务:程序容器)name的音标,name的音标怎么写(微服务:程序容器)

今日福利

遇见大咖

由 CSDN 全新专为技术人打造的高端对话栏目《大咖来了》来啦!

CSDN 创始人&董事长、极客帮创投创始合伙人蒋涛携手京东集团技术副总裁、IEEE Fellow、京东人工智能研究院常务副院长、深度学习及语音和语言实验室负责人何晓冬,来也科技 CTO 胡一川,共话中国 AI 应用元年来了,开发者及企业的路径及发展方向!

2、name的音标怎么写

name的音标怎么写?

name的美式音标为[neɪm],英式音标为[neɪm]。name的用法:name作名词的基本意思是名字,名称,可以是人的名字,也可以是动物、事物或地方的名称,是可数名词。

name还可作名人的意思。

name作名声,名誉的意思时,一般指社会对人或某事物的评价,是单数名词,可与不定冠词a连用。name可作定语修饰其他名词,意为有名的,名声卓著的。name用作动词时意思是给某人取名,说出某人的名字,引申可指提名,任命,还可指列举。表示以某人的名字起名,英式英语常说name after,美式英语则用name for来表示。

name英文怎么读

音标:英[neɪm]、美[neɪm]。 意思:1、n. 名称;姓名;名义;名誉;名人。

2、v. 命名;取名;说出( ... 的名字)。

举例:1、The committee's name has been acronymed NACA.该委员会的名称被缩合成NACA。2、Rubella is just another name for German measles.风疹只是德国麻疹的另一个名称。用法1、name作名词的基本意思是“名字,名称”,可以是人的名字,也可以是动物、事物或地方的名称,是可数名词。2、name还可作“名人”解。

3、name作“名声,名誉”解时,一般指社会对人或某事物的评价,是单数名词,可与不定冠词a连用。

name中文怎么读

name中文读作:内幕音标:英 [neɪm]美 [neɪm]n. 名称;姓名;名义;名誉;名人v. 命名;取名;说出( ... 的名字)adj. 著名的词语用法1、name作名词的基本意思是“名字,名称”,可以是人的名字,也可以是动物、事物或地方的名称,是可数名词。name还可作“名人”解。

2、name作“名声,名誉”解时,一般指社会对人或某事物的评价,是单数名词,可与不定冠词a连用。

3、name用作动词时意思是“给…取名”“说出…的名字”,引申可指“提名,任命”,还可指“列举”。4、name是及物动词,可接名词或代词作宾语。作“取名”解时,可接名词充当补足语的复合宾语; 作“提名,任命”解时可接“(to be/as/for+) n. ”充当补足语的复合宾语。扩展资料:相关例句用作名词(n.)1、She signed the poem with her real name.她在诗后署上了自己的真实姓名。

2、He refused to disclose his name and address.他拒绝透露自己的姓名和地址。3、He has lent his name to the lofty cause.他以自己的名义支持这一崇高的事业。4、You can name the bookmark at design time.您可以在设计时命名书签。

5、She was named after her grandmother.她是根据她祖母的名字命名的。

本文关键词:name的音标怎么写怎么读,new怎么读音发音 音标,name的音标怎么写读,a到z的26个字母音标,name的音标怎么写?/ai/?。这就是关于《name的音标,name的音标怎么写(微服务:程序容器)》的所有内容,希望对您能有所帮助!

音标

最新文章