iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >go语言生成器code generator怎么使用
  • 682
分享到

go语言生成器code generator怎么使用

2023-06-30 14:06:35 682人浏览 八月长安
摘要

这篇文章主要介绍“Go语言生成器code generator怎么使用”,在日常操作中,相信很多人在go语言生成器code generator怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家

这篇文章主要介绍“Go语言生成器code generator怎么使用”,在日常操作中,相信很多人在go语言生成器code generator怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”go语言生成器code generator怎么使用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

    代码生成器介绍

    client-go为每种k8s内置资源提供了对应的clientsetinfORMer。那么我们要监听和操作自定义资源对象,应该如何做呢?

    方式一:使用client-go提供的dynamicClient来操作自定义资源对象,当然由于dynamicClient是基于RESTClient实现的,所以我们可以使用RESTClient来达到同样的目的。

    方式二: 使用conde-generator来帮我们生成我们需要的代码,这样我们就可以像使用client-go为k8s内置资源对象提供的方式监听和操作自定义资源了。

    code-generator

    code-generator 就是 kubernetes 提供的一个用于代码生成的项目,它提供了以下工具为 Kubernetes 中的资源生成代码:

    • deepcopy-gen: 生成深度拷贝方法,为每个 T 类型生成 func (t* T) DeepCopy() *T 方法,api 类型都需要实现深拷贝

    • client-gen: 为资源生成标准的 clientset

    • informer-gen: 生成 informer,提供事件机制来响应资源的事件

    • lister-gen: 生成 Lister,为 get 和 list 请求提供只读缓存层(通过 indexer 获取)

    Informer 和 Lister 是构建控制器的基础,使用这4个代码生成器可以创建全功能的、和 Kubernetes 上游控制器工作机制相同的 production-ready 的控制器。

    code-generator 还包含一些其它的代码生成器,例如 Conversion-gen 负责产生内外部类型的转换函数、Defaulter-gen 负责处理字段默认值。

    大部分的生成器支持--input-dirs参数来读取一系列输入包,处理其中的每个类型,然后生成代码:

    部分代码生成到输入包所在目录,例如 deepcopy-gen 生成器,也可以使用参数--output-file-base "zz_generated.deepcopy" 来定义输出文件名

    其它代码生成到 --output-package 指定的目录,例如 client-gen、informer-gen、lister-gen 等生成器

    示例

    接来下我们使用code-generator进行实战演示:

    首先我们将项目拉到本地:

    git clone https://GitHub.com/kubernetes/code-generator.git$ git checkout 0.23.3

    然后我们进入到cmd目录下,就会看到我们上面介绍的工具:

    go语言生成器code generator怎么使用

    接着我们对client-gen,deepcopy-gen,infromer-gen,lister-gen进行安装,会安装到GOPATH的bin目录下:

    # 进行安装$ go install ./cmd/{client-gen,deepcopy-gen,informer-gen,lister-gen}# 获取GOPATH路径$ go env | grep GOPATHGOPATH="/Users/Christian/go"# 查看ls /Users/Christian/go/binclient-gen     deepcopy-gen   goimports      lister-gencontroller-gen defaulter-gen  informer-gen   type-scaffold

    发现我们已经成功的安装了,这时候我们就可以直接使用这些工具了,比如我们可以使用--help命令来查看如何使用client-gen:

    go语言生成器code generator怎么使用

    当然通常情况下我们不会去单独的使用某一个工具。

    接下来我们来创建我们的项目,此处我们可以仿照sample controller项目进行编写:

    $ mkdir operator-test && cd operator-test$ go mod init operator-test$ mkdir -p pkg/apis/example.com/v1➜  operator-test tree.├── go.mod├── go.sum└── pkg    └── apis        └── example.com            └── v1                ├── doc.go                ├── reGISter.go                └── types.go4 directories, 5 files

    接下来我们对v1下面的三个go文件进行填充(可以直接复制sample-controller,对其进行做简单修改):

    doc.go主要是用来声明要使用deepconpy-gen以及groupName。

    // pkg/crd.example.com/v1/doc.go// +k8s:deepcopy-gen=package// +groupName=example.compackage v1

    types.go主要是定义crd资源对应的go中的结构。

    // pkg/crd.example.com/v1/types.gopackage v1import metav1 "k8s.io/apiMachinery/pkg/apis/meta/v1"// +genclient// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// Bar is a specification for a Bar resourcetype Bar struct {    metav1.TypeMeta   `JSON:",inline"`    metav1.ObjectMeta `json:"metadata,omitempty"`    Spec BarSpec `json:"spec"`    // Status BarStatus `json:"status"`}// BarSpec is the spec for a Bar resourcetype BarSpec struct {    DeploymentName string `json:"deploymentName"`    Image          string `json:"image"`    Replicas       *int32 `json:"replicas"`}// BarStatus is the status for a Bar resourcetype BarStatus struct {    AvailableReplicas int32 `json:"availableReplicas"`}// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// BarList is a list of Bar resourcestype BarList struct {    metav1.TypeMeta `json:",inline" :"metav1.TypeMeta"`    metav1.ListMeta `json:"metadata" :"metav1.ListMeta"`    Items []Bar `json:"items" :"items"`}

    register.go顾名思义,就是注册资源。

    package v1import (    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"    "k8s.io/apimachinery/pkg/runtime"    "k8s.io/apimachinery/pkg/runtime/schema")// SchemeGroupVersion is group version used to register these objectsvar SchemeGroupVersion = schema.GroupVersion{Group: "example.com", Version: "v1"}// Kind takes an unqualified kind and returns back a Group qualified GroupKindfunc Kind(kind string) schema.GroupKind {    return SchemeGroupVersion.WithKind(kind).GroupKind()}// Resource takes an unqualified resource and returns a Group qualified GroupResourcefunc Resource(resource string) schema.GroupResource {    return SchemeGroupVersion.WithResource(resource).GroupResource()}var (    // SchemeBuilder initializes a scheme builder    SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)    // AddToScheme is a global function that registers this API group & version to a scheme    AddToScheme = SchemeBuilder.AddToScheme)// Adds the list of known types to Scheme.func addKnownTypes(scheme *runtime.Scheme) error {    scheme.AddKnownTypes(SchemeGroupVersion,        &Bar{},        &BarList{},    )    metav1.AddToGroupVersion(scheme, SchemeGroupVersion)    return nil}

    这时候会发现&Bar{},&BarLis{}会报错,这是因为我们还没有为其实现deepcopy方法。

    由于在自动生成代码的时候,需要指定header的信息,所以我们为了方便,可以将code-generator项目下的hack包直接拷贝到我们当前项目根目录下。

    接下来我们使用code-generator来为我们自动生成代码:

    # 运行 code-generator/generate-group.sh./../../github/code-generator/generate-groups.sh all \# 指定 group 和 version,生成deeplycopy以及clientoperator-test/pkg/client operator-test/pkg/apis crd.example.com:v1 \# 指定头文件--go-header-file=./hack/boilerplate.go.txt \# 指定输出位置,默认为GOPATH--output-base ../Generating deepcopy funcsGenerating clientset for crd.example.com:v1 at operator-test/pkg/client/clientsetGenerating listers for crd.example.com:v1 at operator-test/pkg/client/listersGenerating informers for crd.example.com:v1 at operator-test/pkg/client/informers

    这时候我们再来查看项目结构:

    ➜  operator-test tree.├── go.mod├── go.sum├── hack│   └── boilerplate.go.txt└── pkg    ├── apis    │   └── crd.example.com    │       └── v1    │           ├── doc.go    │           ├── register.go    │           ├── types.go    │           └── zz_generated.deepcopy.go    └── client        ├── clientset        │   └── versioned        │       ├── clientset.go        │       ├── doc.go        │       ├── fake        │       │   ├── clientset_generated.go        │       │   ├── doc.go        │       │   └── register.go        │       ├── scheme        │       │   ├── doc.go        │       │   └── register.go        │       └── typed        │           └── crd.example.com        │               └── v1        │                   ├── bar.go        │                   ├── crd.example.com_client.go        │                   ├── doc.go        │                   ├── fake        │                   │   ├── doc.go        │                   │   ├── fake_bar.go        │                   │   └── fake_crd.example.com_client.go        │                   └── generated_expansion.go        ├── informers        │   └── externalversions        │       ├── crd.example.com        │       │   ├── interface.go        │       │   └── v1        │       │       ├── bar.go        │       │       └── interface.go        │       ├── factory.go        │       ├── generic.go        │       └── internalinterfaces        │           └── factory_interfaces.go        └── listers            └── crd.example.com                └── v1                    ├── bar.go                    └── expansion_generated.go22 directories, 29 files

    这时候我们就可以像操作内置资源一样,操作我们的自定义资源了。

    我们先准备crd以及对应的cr,这边也是可以直接从sample-controller项目进行拷贝,做简单的修改即可。

    # manifests/example.com_bars.yaml---apiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata:  annotations:    controller-gen.kubebuilder.io/version: (devel)  creationTimestamp: null  name: bars.crd.example.comspec:  group: crd.example.com  names:    kind: Bar    listKind: BarList    plural: bars    singular: bar  scope: Namespaced  versions:  - name: v1    schema:      openAPIV3Schema:        description: Bar is a specification for a Bar resource        properties:          apiVersion:            description: 'APIVersion defines the versioned schema of this representation              of an object. Servers should convert recognized schemas to the latest              internal value, and may reject unrecognized values. More info: Https://git.k8s.io/commUnity/contributors/devel/sig-architecture/api-conventions.md#resources'            type: string          kind:            description: 'Kind is a string value representing the REST resource this              object represents. Servers may infer this from the endpoint the generated              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'            type: string          metadata:            type: object          spec:            description: BarSpec is the spec for a Bar resource            properties:              deploymentName:                type: string              image:                type: string              replicas:                format: int32                type: integer            required:            - deploymentName            - image            - replicas            type: object        required:        - spec        type: object    served: true    storage: true# manifests/cr.yaml---apiVersion: crd.example.com/v1kind: Barmetadata:  name: bar-demo  namespace: defaultspec:  image: "Nginx:1.17.1"  deploymentName: example-bar  replicas: 2

    接下来我们来编写main函数,这时候我们就可以使用client-go像操作我们内置资源一样,操作crd资源了。

    package mainimport (    "context"    "fmt"    v1 "k8s.io/apimachinery/pkg/apis/meta/v1"    "k8s.io/client-go/tools/cache"    "k8s.io/client-go/tools/clientcmd"    "log"    clientSet "operator-test/pkg/client/clientset/versioned"    "operator-test/pkg/client/informers/externalversions")func main() {    config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)    if err != nil {        log.Fatalln(err)    }    clientset, err := clientSet.NewForConfig(config)    if err != nil {        log.Fatalln(err)    }    list, err := clientset.CrdV1().Bars("default").List(context.TODO(), v1.ListOptions{})    if err != nil {        log.Fatalln(err)    }    for _, bar := range list.Items {        fmt.Println(bar.Name)    }    factory := externalversions.NewSharedInformerFactory(clientset, 0)    factory.Crd().V1().Bars().Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{        AddFunc:    nil,        UpdateFunc: nil,        DeleteFunc: nil,    })    // todo}// ====// 程序输出结果:bar-demo

    代码生成tag

    在我们上面的示例中,我们在源码中添加了很多tag,我们使用这些tag来标记一些供生成器使用的属性。这些tag主要分为两类:

    • doc.go的package语句智商提供的全局tag

    • 在需要被处理的类型上提供局部tag

    tag的使用方法如下所示:

    // +tag-name// 或者// +tag-name=value

    我们可以看到 tag 是通过注释的形式存在的,另外需要注意的是 tag 的位置非常重要,很多 tag 必须直接位于 type 或 package 语句的上一行,另外一些则必须和 go 语句隔开至少一行空白。

    全局tag

    必须在目标包的doc.go文件中声明,一般路径为pkg/apis/<apigroup>/<version>/doc.go,如下所示:

    // 为包中任何类型生成深拷贝方法,可以在局部 tag 覆盖此默认行为// +k8s:deepcopy-gen=package // groupName 指定 API 组的全限定名// 此 API 组的 v1 版本,放在同一个包中// +groupName=crd.example.compackage v1

    注意:空行不能省略

    局部tag

    局部tag要么直接声明在类型之前,要么位于类型之前的第二个注释块中。下面的 types.go 中声明了 CR 对应的类型:

    // 为当前类型生成客户端,如果不加此注解则无法生成 lister、informer 等包// +genclient// 提示此类型不基于 /status 子资源来实现 spec-status 分离,产生的客户端不具有 UpdateStatus 方法// 否则,只要类型具有 Status 字段,就会生成 UpdateStatus 方法// +genclient:noStatus// 为每个顶级 API 类型添加,自动生成 DeepCopy 相关代码// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// K8S 资源,数据库type Database struct {    metav1.TypeMeta   `json:",inline"`    metav1.ObjectMeta `json:"metadata,omitempty"`    Spec DatabaseSpec `json:"spec"`}// 不为此类型生成深拷贝方法// +k8s:deepcopy-gen=false// 数据库的规范type DatabaseSpec struct {    User     string `json:"user"`    PassWord string `json:"password"`    Encoding string `json:"encoding,omitempty"`}// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// 数据库列表,因为 list 获取的是列表,所以需要定义该结构type DatabaseList struct {    metav1.TypeMeta `json:",inline"`    metav1.ListMeta `json:"metadata"`    Items []Database `json:"items"`}

    在上面 CR 的定义上面就通过 tag 来添加了自动生成相关代码的一些注释。此外对于集群级别的资源,我们还需要提供如下所示的注释:

    // +genclient:nonNamespaced// 下面的 Tag 不能少// +genclient

    另外我们还可以控制客户端提供哪些 HTTP 方法:

    // +genclient:noVerbs// +genclient:onlyVerbs=create,delete// +genclient:skipVerbs=get,list,create,update,patch,delete,deleteCollection,watch// 仅仅返回 Status 而非整个资源// +genclient:method=Create,verb=create,result=k8s.io/apimachinery/pkg/apis/meta/v1.Status// 下面的 Tag 不能少// +genclient

    使用 tag 定义完需要生成的代码规则后,执行上面提供的代码生成脚本即可自动生成对应的代码了。

    补充

    除了上面介绍的代码生成方式,我们还可以直接使用sample-controller项目提供的hack/update-condegen.sh脚本。

    #!/usr/bin/env bashset -o errexitset -o nounsetset -o pipefailSCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..# 代码生成器包的位置CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}# generate-groups.sh <generators> <output-package> <apis-package> <groups-versions>#                    使用哪些生成器,可选值 deepcopy,defaulter,client,lister,informer,逗号分隔,all表示全部使用#                    输出包的导入路径  #                    CR 定义所在路径#                    API 组和版本bash "${CODEGEN_PKG}"/generate-groups.sh "deepcopy,client,informer,lister" \  k8s.io/sample-controller/pkg/generated k8s.io/sample-controller/pkg/apis \  samplecontroller:v1alpha1 \  --output-base "$(dirname "${BASH_SOURCE[0]}")/../../.." \  --go-header-file "${SCRIPT_ROOT}"/hack/boilerplate.go.txt# 自动生成的源码头部附加的内容:#   --go-header-file "${SCRIPT_ROOT}"/hack/custom-boilerplate.go.txt

    执行上面的脚本后,所有 API 代码会生成在 pkg/apis 目录下,clientsets、informers、listers 则生成在 pkg/generated 目录下。不过从脚本可以看出需要将 code-generator 的包放置到 vendor 目录下面,现在我们都是使用 go modules 来管理依赖保,我们可以通过执行 go mod vendor 命令将依赖包放置到 vendor 目录下面来。

    我们还可以进一步提供 hack/verify-codegen.sh 脚本,用于判断生成的代码是否 up-to-date:

    #!/usr/bin/env bashset -o errexitset -o nounsetset -o pipefail# 先调用 update-codegen.sh 生成一份新代码# 然后对比新老代码是否一样SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..DIFFROOT="${SCRIPT_ROOT}/pkg"TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg"_tmp="${SCRIPT_ROOT}/_tmp"cleanup() {  rm -rf "${_tmp}"}trap "cleanup" EXIT SIGINTcleanupmkdir -p "${TMP_DIFFROOT}"cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}""${SCRIPT_ROOT}/hack/update-codegen.sh"echo "diffing ${DIFFROOT} against freshly generated codegen"ret=0diff -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$?cp -a "${TMP_DIFFROOT}"/* "${DIFFROOT}"if [[ $ret -eq 0 ]]then  echo "${DIFFROOT} up to date."else  echo "${DIFFROOT} is out of date. Please run hack/update-codegen.sh"  exit 1fi

    到此,关于“go语言生成器code generator怎么使用”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

    --结束END--

    本文标题: go语言生成器code generator怎么使用

    本文链接: https://www.lsjlt.com/news/329387.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • go语言生成器code generator怎么使用
      这篇文章主要介绍“go语言生成器code generator怎么使用”,在日常操作中,相信很多人在go语言生成器code generator怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家...
      99+
      2023-06-30
    • go语言代码生成器code generator使用示例介绍
      目录代码生成器介绍code-generator示例代码生成tag全局tag局部tag补充代码生成器介绍 client-go为每种k8s内置资源提供了对应的clientset和info...
      99+
      2024-04-02
    • go语言切片怎么生成
      本篇内容介绍了“go语言切片怎么生成”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在go语言中,切片(slice)是对数组的一个连续片段的引...
      99+
      2023-07-04
    • Python浅析生成器generator的使用
      目录一、创建生成器1.创建生成器的方式12.创建生成器的方式2二、遍历生成器的方式三、总结一、创建生成器 通过列表⽣成式,我们可以直接创建⼀个列表。 但是,受到内存限制,列表容量肯定...
      99+
      2024-04-02
    • javascript之generator生成器函数与asnyc/await语法糖怎么使用
      这篇文章主要讲解了“javascript之generator生成器函数与asnyc/await语法糖怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“javascript之generat...
      99+
      2023-07-05
    • Go语言集成开发环境之VS Code安装使用
      目录Go语言集成开发环境之VS Code安装使用下载与安装安装中文简体插件安装Go开发扩展变更编辑器主题安装Go语言开发工具包配置VSCode开启自动保存配置代码片段快捷键Go语言集...
      99+
      2024-04-02
    • JavaScript前端迭代器Iterator与生成器Generator怎么使用
      这篇文章主要介绍“JavaScript前端迭代器Iterator与生成器Generator怎么使用”,在日常操作中,相信很多人在JavaScript前端迭代器Iterator与生成器Generator怎么使...
      99+
      2024-04-02
    • Go语言中怎么生成二维码
      Go语言中怎么生成二维码,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Go语言生成二维码图片使用Go语言编程时,生成任意内容的二维码是非常...
      99+
      2024-04-02
    • 详解mybatis generator代码生成器的使用
      MyBatis Generator简介 MyBatis Generator(MBG)是MyBatis MyBatis 和iBATIS的代码生成器。它将为所有版本的MyBatis以及...
      99+
      2024-04-02
    • mybatis-generator代码生成器的使用与配置
      一、MyBatis Generator 简介 官网的MyBatis Generator使用介绍,请点击下面的链接:链接 MyBatis Generator 生成的文件包含三类: (1)Model实体文件,一个数据库表对应生成一个 Model...
      99+
      2023-09-04
      mybatis java mysql
    • MyBatis Generator ORM层面的代码自动生成器怎么使用
      这篇文章主要介绍了MyBatis Generator ORM层面的代码自动生成器怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇MyBatis Generator ...
      99+
      2023-07-05
    • 使用R语言怎么生成频数表
      使用R语言怎么生成频数表?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。什么是R语言R语言是用于统计分析、绘图的语言和操作环境,属于GNU系统的一个自由、免费、源...
      99+
      2023-06-14
    • 如何用Go语言生成一个排列
      如何用Go语言生成一个排列,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。算法目前,生成一个序列的...
      99+
      2024-04-02
    • 怎么使用GO语言
      这篇文章主要讲解了“怎么使用GO语言”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用GO语言”吧!什么是 GVMGo 语言版本管理器(GVM)是管理 Go 语言环境的开源工具。GVM ...
      99+
      2023-06-16
    • 使用R语言怎么生成一个随机数
      这篇文章给大家介绍使用R语言怎么生成一个随机数,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1. 均匀分布函数: runif(n, min=0, max=1),n 表示生成的随机数数量,min 表示均匀分布的下限,ma...
      99+
      2023-06-13
    • 如何在Go语言中使用Windows API生成二维码?
      在Go语言中使用Windows API生成二维码可以帮助开发者在Windows平台下快速生成高质量的二维码。本文将介绍如何使用Go语言结合Windows API生成二维码。 一、安装必要的库 在使用Windows API生成二维码之前,我们...
      99+
      2023-09-14
      二维码 windows 函数
    • 如何使用Go语言生成高质量的二维码?
      随着智能手机和移动互联网的普及,二维码越来越成为企业和个人传播信息的一种重要方式。在二维码的制作过程中,Go语言提供了很多方便快捷的工具,本文将介绍如何使用Go语言生成高质量的二维码。 一、Go语言生成二维码的基本原理 二维码的生成是通过将...
      99+
      2023-11-15
      二维码 面试 load
    • 您知道如何使用Go语言生成二维码吗?
      Go语言(又称Golang)是由Google开发的一门静态类型的编程语言,它旨在提高程序员的工作效率。Go语言具有高效的编译速度、良好的并发性能、简单易学的语法等特点,因此被越来越多的开发者所青睐。在本篇文章中,我们将介绍如何使用Go语言生...
      99+
      2023-10-16
      spring linux 二维码
    • 二维码生成器:使用Go语言和Linux系统轻松实现!
      二维码是一种二维条码,它可以存储大量信息,如URL、联系人信息、文本等。它已经被广泛应用于移动支付、广告传媒、商业推广等领域。而二维码生成器可以快速生成各种二维码,为人们提供便利。本文将介绍如何使用Go语言和Linux系统轻松实现一个二维码...
      99+
      2023-10-16
      spring linux 二维码
    • Go语言dolphinscheduler怎么使用
      这篇文章主要介绍了Go语言dolphinscheduler怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Go语言dolphinscheduler怎么使用文章都会有所收获,下面我们一起来看看吧。自动化为什...
      99+
      2023-07-02
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作