File: istio/pilot/pkg/model/log.go
在Istio项目中,istio/pilot/pkg/model/log.go
文件的作用是定义了Istio Pilot的日志记录功能。
该文件中定义了一个名为log
的全局日志记录器,并且还定义了一些与日志记录相关的变量,如verbose
、verboseCount
、disableVerbose
、debug
、disableDebug
等。
log全局变量:
log
是基于github.com/istio/gogo-genproto/googleapis/logging/v2
库的一个日志记录器对象。它允许Pilot在不同的级别(如error、warn、info、debug)进行日志记录,并通过配置日志输出目标(如控制台、文件)来控制日志的输出方式。
verbose变量:
verbose
是一个存储布尔值的全局变量,用于控制是否启用详细信息日志记录。当设置为true时,Pilot会记录更详细的日志信息。
verboseCount变量:
verboseCount
是一个整数变量,用于记录详细信息日志的计数。它表示在启动Pilot之后记录的详细信息日志的数量。
disableVerbose变量:
disableVerbose
是一个布尔变量,用于控制是否禁用详细信息日志记录。
debug变量:
debug
是一个存储布尔值的全局变量,用于控制是否启用调试日志记录。当设置为true时,Pilot会记录调试信息日志。
disableDebug变量:
disableDebug
是一个布尔变量,用于控制是否禁用调试日志记录。
通过这些变量,Istio Pilot可以方便地进行日志记录,并根据需要调整日志级别和输出方式,以便于故障排除、性能分析和系统监控等操作。
File: istio/pilot/pkg/model/service.go
在istio/pilot/pkg/model/service.go文件中,包含了许多结构体和函数,用于定义和操作与服务相关的模型。
接下来是一些重要的结构体和它们的作用:
接下来列出一些重要的函数和它们的作用:
File: istio/pilot/pkg/model/authentication.go
authentication.go是Istio Pilot中的一个文件,它定义了一些与身份认证相关的结构体和函数。
MutualTLSMode是一个枚举类型,用于表示一对服务之间的双向TLS(Mutual TLS)的模式。该枚举类型包括:NONE、ISTIO_MUTUAL、MUTUAL_TLS_PERMISSIVE和MUTUAL_TLS_STRICT。
AuthenticationPolicies是一个结构体,用于存储由配置文件定义的服务的身份认证策略。它包括一个DefaultPolicy字段,表示默认的身份认证策略,以及一个PermissiveMode字段,表示是否以宽容模式(Permissive Mode)运行。
String是一个函数,用于将MutualTLSMode转换为字符串表示。
ConvertToMutualTLSMode是一个函数,用于将字符串表示的MutualTLSMode转换为实际的MutualTLSMode枚举值。
initAuthenticationPolicies是一个函数,用于初始化身份认证策略。它接收一个JSON格式的配置文件作为参数,并将其解析为AuthenticationPolicies结构。
addRequestAuthentication是一个函数,用于将请求身份认证规则添加到配置中。
addPeerAuthentication是一个函数,用于将对等身份认证规则添加到配置中。
GetNamespaceMutualTLSMode是一个函数,用于获取给定名称空间的双向TLS模式。
GetJwtPoliciesForWorkload是一个函数,用于获取给定工作负载的JWT策略。
GetPeerAuthenticationsForWorkload是一个函数,用于获取给定工作负载的对等身份认证规则。
GetRootNamespace是一个函数,用于获取Istio体系结构的根名称空间。
GetVersion是一个函数,用于获取当前配置文件的版本。
GetAmbientPolicyConfigName是一个函数,用于获取环境策略配置的名称。
getConfigsForWorkload是一个函数,用于根据工作负载的名称和名称空间获取相应的配置信息。
总之,authentication.go文件中定义了与身份认证相关的结构体和函数,它们用于处理和管理Istio中的身份验证策略和配置。
File: istio/pilot/pkg/model/gateway.go
在Istio项目中,gateway.go文件是Istio Pilot中用于处理网关相关逻辑的文件。它定义了一些结构体和函数来解析和处理网关配置信息。
typeTag变量是用于标识网关配置的类型。nameTag变量用于标识网关配置的名称。totalRejectedConfigs变量是用于记录被拒绝的网关配置数量的计数器。
ServerPort结构体用于表示网关配置中的服务端口信息,包括端口号和协议。MergedServers结构体是一组合并后的服务端口信息,用于表示一个网关实例中的所有服务端口信息。
TLSServerInfo结构体表示网关配置中的TLS相关信息,包括证书和私钥等。MergedGateway结构体是合并后的网关信息,包括网关名称、监听地址和监听端口等。
GatewayPortMap结构体用于记录网关的端口映射信息,包括网关名称和端口映射表。
RecordRejectedConfig函数用于记录被拒绝的网关配置数量。MergeGateways函数用于合并多个网关配置。udpSupportedPort函数用于判断指定端口是否支持UDP协议。resolvePorts函数用于解析网关配置中的端口号。
canMergeProtocols函数用于判断两个协议是否可以合并。GetSNIHostsForServer函数用于获取网关的SNI主机列表。CheckDuplicates函数用于检查网关配置是否存在重复。gatewayRDSRouteName函数用于生成网关的RDS路由名称。
ParseGatewayRDSRouteName函数用于解析网关RDS路由名称并分解为网关名称和监听端口。sanitizeServerHostNamespace函数用于规范化服务端主机名称和命名空间。
getTargetPortMap函数用于获取目标端口映射表,包括服务端口与网关端口的映射关系。
这些函数和变量的目的是为了解析和处理网关配置信息,并进行相关的合并、校验和处理操作。
File: istio/pilot/pkg/model/envoyfilter.go
在Istio项目中,envoyfilter.go
文件是 Istio Pilot 包中的一个文件,负责处理 Envoy 配置过滤器(EnvoyFilter)相关的逻辑。
具体而言,EnvoyFilter
是 Istio 针对 Envoy 代理的一种自定义配置对象,用于通过 Envoy 扩展点实现对请求流量的转发、修改和过滤等行为。envoyfilter.go
文件中的代码主要完成了以下几个方面的功能:
定义了一些常量和变量,包括 wellKnownVersions
变量,用于存储支持的 Envoy 版本,以及相关常量用于创建 EnvoyFilter 对象时设置类型等。
定义了 EnvoyFilterWrapper
结构体,作为 EnvoyFilter 的封装对象。该结构体包括了对 EnvoyFilter 的描述信息,以及应用该 EnvoyFilter 的逻辑等。
定义了 EnvoyFilterConfigPatchWrapper
结构体,作为 Envoy 配置补丁的封装对象。该结构体用于对 Envoy 的配置进行修改。
实现了一些函数,包括:
convertToEnvoyFilterWrapper
函数,用于将原始 JSON 格式的 EnvoyFilter 转换为EnvoyFilterWrapper
对象,方便后续处理和应用。proxyMatch
函数,用于判断 EnvoyFilter 是否与当前请求的代理匹配。Keys
函数,用于从EnvoyFilterWrapper
中获取包含的所有键(例如 HTTPFilter、TCPFilter 等)。KeysApplyingTo
函数,用于获取指定类型(例如 HTTPFilter)的键,这些键会被应用到请求上。Key
函数,用于获取指定类型和名称的键。
这些函数的作用是用于解析、匹配和处理 EnvoyFilter 对象,从而实现对流量的定制化配置和过滤。这些逻辑为 Istio 提供了灵活的扩展性,使得用户可以根据需要对请求流量进行各种方式的处理,例如添加、修改或删除特定的 Envoy 配置。
File: istio/pilot/pkg/model/endpointshards.go
在Istio项目中,istio/pilot/pkg/model/endpointshards.go
文件的作用是定义了与端点分片(Endpoint Shards)相关的模型和操作方法。
以下是文件中的各个变量和结构体的作用:
_
:作为占位符,表示不关心返回的值。shardRegistry
:用于管理端点分片的注册表,存储了所有已注册的端点分片。ShardKey
:用于标识一个端点分片的唯一键。EndpointShards
:表示所有端点分片的集合。EndpointIndex
:表示一个端点分片的索引,用于快速查找具有特定标签的端点。PushType
:用于指定如何将更新推送给代理。EndpointIndexUpdater
:用于更新端点索引的接口。
以下是文件中的各个函数的作用:
ShardKeyFromRegistry
:根据注册表生成一个端点分片的键。String
:将端点分片的键转换为字符串。MarshalText
:将端点分片的键转换为文本格式。Keys
:返回所有已注册端点分片的键。CopyEndpoints
:复制给定端点分片的所有端点列表。DeepCopy
:深度复制给定的端点分片。NewEndpointIndex
:创建一个新的端点索引。clearCacheForService
:清除用于特定服务的缓存。Shardz
:使用给定的选项和注册表将服务分片。ShardsForService
:返回具有特定服务的所有端点分片。GetOrCreateEndpointShard
:获取或创建具有指定键的端点分片。DeleteServiceShard
:删除具有特定键的端点分片。DeleteShard
:删除给定的端点分片。deleteServiceInner
:从注册表中删除具有特定键的端点分片。UpdateServiceEndpoints
:更新具有指定键的端点分片的端点。updateShardServiceAccount
:更新给定端点分片的服务帐户。NewEndpointIndexUpdater
:创建一个用于更新端点索引的EndpointIndexUpdater实例。ConfigUpdate
:处理配置更新事件。EDSUpdate
:处理EDS(Endpoint Discovery Service)更新事件。EDSCacheUpdate
:处理EDS缓存更新事件。SvcUpdate
:处理服务更新事件。ProxyUpdate
:处理代理更新事件。RemoveShard
:移除具有特定键的端点分片。
File: istio/pilot/pkg/model/authorization.go
在Istio项目中,authorization.go
文件的作用是实现与授权策略相关的模型和函数。
该文件中定义了以下几个结构体:
AuthorizationPolicy
:表示单个授权策略的模型。授权策略用于定义应用于入站或出站流量的授权规则,以确定允许哪些请求通过。该结构体包含了诸如规则名称、目标规则、源规则、操作规则等属性。
AuthorizationPolicies
:是授权策略的集合,表示一组授权规则。它是AuthorizationPolicy
结构体的切片,用于存储多个授权策略。
AuthorizationPoliciesResult
:表示AuthorizationPolicies
的查询结果。它包含用于查询和操作授权策略集合的元数据信息以及实际的授权策略集。
authorization.go
中还定义了以下几个函数:
GetAuthorizationPolicies
:用于从授权策略集合中获取特定名称的授权策略。该函数接受授权策略集合和授权策略名称作为参数,并返回匹配的授权策略。
ListAuthorizationPolicies
:用于获取所有授权策略或特定标签的授权策略。该函数接受授权策略集合和可选的标签列表作为参数,并返回与标签匹配的授权策略集合。
这些函数可以用于在Istio的控制平面中执行授权策略的查询和操作,允许用户检索或操作应用于服务流量的授权规则。例如,GetAuthorizationPolicies
可以根据策略名称获取具体的授权策略,而ListAuthorizationPolicies
可以根据标签过滤获取匹配的授权策略集合。
总之,authorization.go
文件中的结构体和函数为Istio的授权策略提供了模型和操作方法,使用户能够管理和控制服务之间的访问权限。
File: istio/pilot/pkg/model/extensions.go
在istio项目中,istio/pilot/pkg/model/extensions.go
文件定义了与扩展相关的模型和函数。
首先,anyListener
是一个存储任意类型监听器的切片,每个监听器表示要应用于环境中的特定网络流量的配置。anyListener
用于在整个系统中存储和传递监听器的信息。
WasmPluginWrapper
结构体表示一个WebAssembly(Wasm)插件的封装,该插件在Istio中用于对流量进行处理。其中,WasmPluginListenerInfo
结构体是一个监听器信息的封装,它包含了Wasm插件的配置参数和其他相关信息。
以下是几个重要的函数和它们的作用:
workloadModeForListenerClass
:根据给定的监听器类名获取工作负载模式,即确定是在Sidecar模式还是非Sidecar模式下使用。MatchListener
:根据给定的监听器定义和目标端口,判断监听器是否与目标匹配。matchTrafficSelectors
:根据给定的目标规则和流量源匹配规则,判断是否匹配。matchMode
:根据给定的源和目标模式,判断匹配的模式。matchPorts
:根据给定的源和目标端口,判断两者是否匹配。convertToWasmPluginWrapper
:将扩展配置转换为Wasm插件封装。toSecretResourceName
:根据给定的Secret名和命名空间,生成用于在Istio中引用Secret资源的名称。buildDataSource
:根据给定的扩展数据源配置,构建数据源对象。buildVMConfig
:根据给定的Wasm插件配置,构建WebAssembly虚拟机的配置对象。
这些函数用于扩展的处理和匹配,在Istio的控制平面中发挥重要作用。
File: istio/pilot/pkg/model/jwks_resolver.go
istio/pilot/pkg/model/jwks_resolver.go文件在Istio项目中的作用是实现JSON Web Key Set(JWKS)的解析和管理。
首先,让我们介绍一些关键变量和数据结构:
接下来是一些重要的数据结构:
以下是一些核心函数的功能描述:
这些函数和变量的作用在于实现了JWKS的解析和管理机制,以及刷新和缓存JWT公钥,从而实现了对JWT的有效验证和使用。
File: istio/pilot/pkg/model/network.go
在istio项目中,istio/pilot/pkg/model/network.go
文件定义了与网络相关的结构体和函数,主要用于管理网关和网络配置。
MinGatewayTTL
和MaxGatewayTTL
变量分别用于定义网关的最小和最大生存时间。NetworkGatewayTestDNSServers
变量定义了用于测试网络网关的DNS服务器地址列表。以下是networkAndCluster
结构体中的变量的作用:
NetworkGateway
定义了网络网关规范。NetworkGatewaysWatcher
用于监听网络网关的变化。NetworkGatewaysHandler
用于处理网络网关的变化。NetworkGateways
存储已知的网络网关列表。NetworkManager
用于管理网络网关的增删改查等操作。networkAndCluster
将网络和集群信息关联起来。NetworkGatewaySet
定义了网络网关的集合。networkGatewayNameCache
用于缓存网络网关的名称和地址信息。nameCacheEntry
定义了网络网关名称和地址的缓存条目。dnsClient
用于与DNS服务器进行通信。
以下是networkAndCluster
结构体中的函数的作用:
AppendNetworkGatewayHandler
用于向网络网关处理列表中添加处理器。NotifyGatewayHandlers
用于通知网络网关处理器执行网关相关的操作。NewNetworkManager
创建一个新的网络管理器实例。reloadGateways
用于重新加载网关列表。reload
用于重新加载网络网关并通知监听器。update
用于更新网络网关。resolveHostnameGateways
用于解析主机名所关联的网关。IsMultiNetworkEnabled
判断是否启用了多网络模式。GetLBWeightScaleFactor
用于获取负载均衡的权重因子。AllGateways
返回所有的网络网关。allGateways
返回所有的网络网关。GatewaysForNetwork
根据网络名称返回相应的网络网关。GatewaysForNetworkAndCluster
根据网络名称和集群名称返回相应的网络网关。networkAndClusterForGateway
根据网络网关名称返回相应的网络和集群信息。networkAndClusterFor
根据网络名称和集群名称返回相应的网络和集群信息。SortGateways
对网关进行排序。gcd
计算最大公约数。lcm
计算最小公倍数。newNetworkGatewayNameCache
创建一个新的网络网关名称缓存。newNetworkGatewayNameCacheWithClient
创建一个新的网络网关名称缓存,并指定DNS客户端。Resolve
用于解析网络网关的名称和地址。cleanupWatches
用于清理非法的观察器。resolveFromCache
从缓存中解析网络网关的名称和地址。resolveAndCache
解析网络网关的名称和地址,并缓存到缓存中。refreshAndNotify
刷新并通知网络网关的信息。resolve
用于解析网关的名称和地址。minimalTTL
用于计算最小的生存时间。newClient
创建一个新的DNS客户端。getReqNames
获取网络网关名称的请求列表。Query
用于查询网络网关的名称和地址。
File: istio/pilot/pkg/model/typed_xds_cache.go
在istio项目中,istio/pilot/pkg/model/typed_xds_cache.go文件的作用是实现xDS缓存的功能。xDS是一个用于配置和管理服务网格中网络和负载均衡的API,而该文件中的代码用于实现对xDS配置的缓存管理。
以下是变量的作用:
以下是结构体的作用:
以下是函数的作用:
通过上面的介绍,可以了解到typed_xds_cache.go文件中实现了对xDS缓存的统计、管理和操作功能,包括缓存命中率、大小和清除等操作。它在Istio的Pilot组件中起到了重要的作用,用于优化和加速对xDS配置的访问。
File: istio/pilot/pkg/model/disabled_ledger.go
在Istio项目中,disabled_ledger.go
文件位于istio/pilot/pkg/model目录中,它主要定义了与分布式配置存储相关的功能。该文件的作用是实现了一个基于内存的禁用存储器,用于存储和管理Istio配置的状态信息。
DisabledLedger
结构体是一个禁用存储器的抽象接口,定义了对配置状态的读取和修改操作。该结构体包含以下几个方法:
Put
方法用于将指定的键值对写入禁用存储器,即将新值覆盖或添加到旧值上。Delete
方法用于从禁用存储器中删除指定的键值对。Get
方法用于从禁用存储器中获取指定键的值。RootHash
方法用于返回禁用存储器中所有键值对的哈希值。GetPreviousValue
方法用于返回禁用存储器中指定键的前一个值。这些方法提供了对禁用存储器的基本操作,使得可以通过禁用存储器来存储和检索Istio配置的状态信息。在禁用存储器中,配置信息以键值对的形式存储,并且可以根据需要进行修改、读取和删除操作。DisabledLedger
结构体提供了一种抽象接口,为其他组件和模块提供了与配置状态交互的方式。
总之,disabled_ledger.go
文件中的DisabledLedger
结构体及其相关方法定义了一个禁用存储器的抽象接口,用于管理和操作Istio配置的状态信息。
File: istio/pilot/pkg/model/virtualservice.go
在Istio项目中的istio/pilot/pkg/model/virtualservice.go
文件是VirtualService的模型定义文件,VirtualService是Istio中用于配置路由规则的对象。
SelectVirtualServices
函数用于从一组VirtualService中选择与给定hosts匹配的VirtualService。
vsHostMatches
函数判断给定的Host是否与VirtualService中定义的一个或多个hosts匹配。
resolveVirtualServiceShortnames
函数用于解析VirtualService的短名称(没有命名空间前缀)。
mergeVirtualServicesIfNeeded
函数根据相同主机的VirtualServices创建一个新的合并的VirtualService,并处理冲突。
mergeHTTPRoutes
函数用于合并VirtualService中的HTTP路由规则。
mergeHTTPRoute
函数用于合并两个HTTP路由规则。
mergeHTTPMatchRequests
函数用于合并两个HTTP匹配请求。
mergeHTTPMatchRequest
函数用于合并两个HTTP匹配请求的头部要求。
hasConflict
函数用于检查两个VirtualService是否存在冲突。
stringMatchConflict
函数用于检查两个字符串匹配是否存在冲突。
isRootVs
函数用于判断给定的VirtualService是否为根VirtualService(根据它是否具有可解析的主机规则)。
UseIngressSemantics
函数用于判断给定的VirtualService是否使用Ingress语义,即是否通过Ingress配置。
UseGatewaySemantics
函数用于判断给定的VirtualService是否使用Gateway语义,即是否通过网关配置。
VirtualServiceDependencies
函数用于获取给定的VirtualService的依赖关系,即在Istio的路由中使用到的其他服务或服务端口。
File: istio/pilot/pkg/model/wasm.go
在Istio项目中,istio/pilot/pkg/model/wasm.go
文件的作用是实现了与Wasm(WebAssembly)相关的代码逻辑。Wasm是一种可移植的二进制指令集,可以在不同的平台上运行。Istio使用Wasm作为扩展Istio代理的一种方式,通过Wasm能够提供自定义的功能和逻辑。
wasm.go
文件中包含了与Wasm相关的结构体和函数。其中,ConstructVMConfig
函数起到了构造Wasm虚拟机配置的作用。函数签名如下:
func ConstructVMConfig(config *vmConfig) (*host.VMConfiguration, error)
该函数接收一个vmConfig
类型的参数,并返回一个VMConfiguration
类型的虚拟机配置。vmConfig
结构体中包含了Wasm实例的相关信息,如存储的路径、环境变量等。
ConstructVMConfig
函数的主要作用是将vmConfig
结构体转换为VMConfiguration
类型的配置,这个配置包含了Wasm实例的运行时环境需要的各种参数和选项。
此外,还有其他一些函数,如ParseVMConfig
函数用于解析从配置文件中读取的Wasm配置信息;ParseHTTPExtension
函数用于解析HTTP扩展配置信息;ConstructFilterConfig
函数用于构造过滤器的配置等。这些函数都是用于实现Wasm相关的功能。
总的来说,istio/pilot/pkg/model/wasm.go
文件主要负责处理与Wasm相关的功能,包括构造Wasm虚拟机配置、解析配置文件、构造过滤器配置等。这些功能对于Istio项目中使用Wasm进行代理扩展非常重要。
File: istio/pilot/pkg/model/credentials/resource.go
在istio项目中,istio/pilot/pkg/model/credentials/resource.go文件的作用是定义了与凭证资源(例如TLS证书和密钥)相关的数据结构和方法。
该文件中定义了几个与凭证资源相关的结构体,其中包括:
以下是几个重要函数的作用:
这些函数的作用是提供了对凭证资源的转换、解析和处理的能力,用于在Istio中管理和配置凭证资源。这些凭证资源可以用于安全性验证、TLS连接等方面,在istio/pilot组件中起到关键作用。
File: istio/pilot/pkg/request/command.go
在Istio项目中,pilot/pkg/request/command.go
文件的作用是定义和处理Pilot的命令请求。
该文件中包含了几个命令相关的结构体和函数,用于接收、解析和执行来自客户端的命令请求。下面分别介绍这些结构体和函数的作用:
Command结构体:这是一个抽象类型,代表了一个命令请求。它包含一个Name
字段用于标识命令的名称,以及一个Params
字段用于存储命令请求的参数。
Commands结构体:这是一个命令请求的集合,包含了多个Command对象。它实现了UnmarshalJSON
方法用于从JSON格式中解析命令请求。
Do函数:这是一个执行命令请求的函数,它接收一个Command
对象作为参数,并根据Command
的Name
字段选择相应的处理函数执行。
以下是Do
函数中定义的几个函数和它们的作用:
doGetProxyConfig
函数:该函数用于获取代理的配置信息。doSetProxyConfig
函数:该函数用于设置代理的配置信息。doStatsD
函数:该函数用于处理与统计相关的命令请求。doVersion
函数:该函数用于返回Pilot的版本信息。
这些函数会根据命令请求的不同参数执行相应的操作,并返回对应的结果。
总之,command.go
文件中定义了Pilot的命令请求的数据结构和处理函数,用于接收、解析和执行来自客户端的命令请求。通过这些命令,可以获取和设置代理的配置信息,并执行与统计和版本相关的操作。
File: istio/pilot/pkg/config/memory/store.go
在Istio项目中,istio/pilot/pkg/config/memory/store.go
文件的作用是实现一个基于内存的数据存储库。这个存储库被用来存储和操作Istio配置对象。
首先,让我们来了解几个变量的作用:
errNotFound
表示在存储库中找不到指定的对象时返回的错误。errAlreadyExists
表示在存储库中创建一个已经存在的对象时返回的错误。errConflict
表示在存储库中更新或删除一个已经被修改的对象时返回的错误。
接下来,让我们来了解几个结构体的作用:
store
结构体是内存数据存储库的主要结构体。它包含一个sync.RWMutex
互斥锁用于保护对存储库的并发访问;一个map
类型的字段来存储配置对象;以及一些元数据来帮助管理存储库的操作。index
结构体用于维护配置对象的索引。它通过对象名称和命名空间来索引对象。versioned
结构体是存储库中存储对象的容器。它包含了一个版本号以及一个指向原始配置对象的指针。
下面是一些函数的作用:
Make
函数用于创建一个新的存储库。MakeSkipValidation
函数与Make
函数类似,但不会对对象的有效性进行验证。newStore
函数用于创建一个新的存储库实例。Schemas
函数返回存储库中对象的架构定义。Get
函数用于根据名称和命名空间获取存储库中的对象。List
函数用于获取存储库中指定命名空间的所有对象。Delete
函数用于从存储库中删除对象。Create
函数用于在存储库中创建新对象。Update
函数用于更新存储库中的对象。UpdateStatus
函数用于更新存储库中对象的状态。Patch
函数用于部分更新存储库中的对象。hasConflict
函数用于检查存储库中的对象是否与给定版本号冲突。
总之,istio/pilot/pkg/config/memory/store.go
文件提供了一个基于内存的存储库,用于存储和操作Istio配置对象。它定义了一些变量、结构体和函数,用于管理存储库的操作和处理对象的创建、更新和删除。
内容由chatgpt生成,仅供参考,不作为面试依据。
仓库地址:github.com/cuishuang/e…