我开始学习Go语言了

概述

由于我身为一个业余者,在过去一个月里开始使用Golang来开发应用程序,我决定将我的感悟和实际调研的结果与大家分享,希望能对大家有一点参考价值。

暫時先分享一下當前的目錄結構。

undefined

左边是根目录,右边是src目录下。对于是否要创建名为src的目录,我一直很犹豫,但最终还是决定创建。

IDE, 开发环境,执行环境。

基於以下原因,我選擇了使用VSCode作為IDE。
– VSCode擁有Golang開發團隊所提供的插件(最初是由Microsoft維護的,但現在已轉交給Golang開發團隊),因此實際上VSCode是標準的選擇。
– 雖然也有JetBrains的GoLand可供使用,但它是付費軟體,所以此次我選擇略過(雖然提供30天的免費試用)。
– 如果使用Intellij Ultimate,還有AWS Toolkit可供使用。

Golang应用程序最终会被编译成一个Linux的ELF格式二进制文件,因此可以轻松地进行Docker化。
在寻找用于运行Golang应用程序的Docker镜像时,我发现了由Google维护的Distroless镜像系列,看起来很不错,所以我决定使用它们。参考网站
此外,我使用了Docker的多阶段构建功能,将构建和运行应用程序的操作都写在了一个简单的Dockerfile中。

FROM golang:1.17.3-bullseye as builder ## -- buildするイメージ

COPY src/ /go/src/
WORKDIR /go/src

RUN GOOS=linux GOARCH=amd64 go build -o hoge main.go

FROM gcr.io/distroless/base:latest ## -- アプリケーション実行するイメージ & 最終的に出来上がるイメージ

COPY --from=builder /go/src/hoge /

ENTRYPOINT [ "/hoge" ]

关于包的构成和架构

作为一位长期从事Java API开发的人来说,我对基于Spring框架的MVC模式非常熟悉。但是,由于Golang没有像Spring这样强大的框架,因此我决定回归编程的本质,考虑采用干净的架构。

根据完整的清洁架构层,并根据目录结构图进行切割。由于这是我第一次接触清洁架构,也不太自信能够很好地解释,因此请参考下面的文章。

对于目录结构和架构的选择,我们团队经过讨论后决定了现在的结构。我们有不断尝试和探索的先驱者们,没有一个确切的答案。虽然我们起初采用了干净架构的分层方式,但后来进行了修正。如果将来遇到问题,我们会再次考虑。

在中文中,可以这样表达:Web框架是Gin。

选择架构之后就是选择框架。
尽管GitHub上的星星数量并不是唯一的指标,但Gin确实拥有最多的星星数量,而且它的开发活跃并且有很多可以参考的日文网站,所以我选择了Gin,认为它很不错。
我认为Gin的特点还有以下几个方面。

    • 速い

 

    軽量

JetBrains先生在调查报告中也获得了第一名,这是链接。
对于各种框架的比较也可以参考一下。

编译

由于Golang支持的操作系统/ CPU架构以及下面的命令,因此可以根据不同的环境进行编译。

go tool dist list
...(一部省略)
linux/386
linux/amd64
linux/arm
linux/arm64
...(一部省略)

这次我们的正式环境预计采用AWS的ECS Fargate,最近刚刚发布了支持arm64的版本,因此我们决定准备linux/amd64和linux/arm64的容器。(实际使用哪个还未确定,但据说arm64更节能并能节约费用。)

关于编译选项的现场和开发用途
-race:类似于检查线程安全性(实际上有一些文章说如果添加它会使应用程序变慢,所以检查只在开发环境中进行,不添加到编译用于生产环境)
-w -s:不添加此选项会包含调试信息,所以在生产环境中不添加。

// 開発用
go build -race -o hoge main.go

// 本番用
go build -o hoge main.go -ldflags "-w -s"

在进行交叉编译时需要注意事项。无法使用-race选项进行交叉编译。详细信息请点击此处。
例如:在amd64服务器上进行arm64编译时。

关于Makefile
在Go语言中,使用Makefile作为编译器语言是主流趋势。
将构建命令和环境配置命令统一放在Makefile中非常方便。

如果将开发环境和生产环境的编译选项进行区分,并将其整理到Makefile中,就可以通过一个make命令实现执行。

# disable symbol table and dwarf
GO_LDFLAGS_SYMBOL:=
ifeq ($(HOGE_ENV),prod)
    GO_LDFLAGS_SYMBOL:=-w -s
endif

GO_LDFLAGS:=$(GO_LDFLAGS_SYMBOL)

# race detector
GO_BUILD_RACE:=-race
ifeq ($(HOGE_ENV),prod)
    GO_BUILD_RACE:=
endif

# go build
GO_BUILD:=$(GO_BUILD_RACE) -ldflags "$(GO_LDFLAGS)"

.PHONY: build
build:
    GOOS=linux GOARCH=amd64 go build -o hoge $(GO_BUILD) main.go
# 開発環境用build
HOGE_ENV=dev make build

# 本番環境用build
HOGE_ENV=prod make build

使用图书馆

蝰蛇

支持JSON、YAML、TOML等配置文件的库。
由于有很多可供参考的资源,我们在这里做简略介绍,只介绍一下具体的使用方法。我们是与go:embed结合使用的。
go:embed提供了将静态文件嵌入到已编译的ELF格式二进制文件中的功能。

├── config.go
└── yaml
    ├── config.prod.yml
    └── config.dev.yml
database:
  postgres:
    name: hoge
    host: localhost
    port: 5432
    user: user
    pass: password

如果假设在上述的目录结构中保存了每个环境的设置(如数据库设置),那么config.go的内容将如下。

type Config struct {
    Database struct {
        Postgres struct {
            Name string
            Host string
            Port string
            User string
            Pass string
        }
    }
}

var (
    //go:embed yaml/*
    staticYamlDir embed.FS
)

func LoadConfig() *Config {
    setDefaultEnv()
    hogeEnv := viper.GetString("env")
    fileName := "yaml/config." + hogeEnv + ".yml"
    viper.SetConfigName("config." + hogeEnv)
    viper.SetConfigType("yaml")
    viper.AddConfigPath("config/yaml")

    b, err := staticYamlDir.ReadFile(fileName)

    if err != nil {
        panic("Failed to read config.")
    }

    if err := viper.ReadConfig(bytes.NewReader(b)); err != nil {
        panic("Failed to load config.")
    }

    var c Config

    if err := viper.Unmarshal(&c); err != nil {
        panic("Failed to unmarshal config.")
    }

    return &c
}

func setDefaultEnv() {
    viper.SetEnvPrefix("hoge")
    viper.BindEnv("env")
    viper.AutomaticEnv()
    viper.SetDefault("env", "dev")
}

通过设置名为HOGE_ENV的环境变量,可以在应用程序启动时加载不同的配置文件,因此可以将环境特定的设置分别存储在不同文件中进行管理。

sqlboiler (SQL锅炉)

这是一个ORM库。如何使用将被省略。
虽然有着著名的GORM等,但我们选择了sqlboiler,理由如下。

    • schemaからコード生成がやりやすい

 

    • 静的に型付けされており、実行時にリフレクションを使う必要がないため高速

 

    • migration機能はないがflywayとかでカバーできる

 

    • 生queryがかける

 

    relationもサポート

空气

Golang 是一种编译型语言,因此在开发过程中需要频繁进行修改、构建和执行的循环操作。
air 是一款可以自动化该循环过程的所谓热重载库,能够提高在本地进行开发的效率。

感受

尽管无法像Java那样通过注解自动完成一些操作,但我认为Golang的特点是代码编写起来比较直接。(尽管Java本身有强大的Spring框架作为武器,所以不仅仅是语言本身的比较)

优点:

    • 新卒でもコード見ればある程度理解できるようなわかりやすさ

 

    • 軽量、高速

 

    クラウドやコンテナ技術、マイクロサービスなどと親和性が高い

麻煩之处:Golang没有异常的概念,必须始终进行if err != nil的判断。

Go语言因为其简洁的设计理念与其他语言有所区别,并获得了广泛的支持,所以可能有些地方使用起来会有些困难,但感觉未来还是会进一步变得更加友好。

最后

在学习一门新语言时,网络上有很多零散的信息,但实际尝试后可能会发现有些方法已经过时,或者是使用反例来构建。因此,建议最先阅读官方文档。特别是对于Golang而言,官方文档相当完善且易读,敬请参阅。

    • オフィシャルドキュメント

Effective go ※これとかは必ず読んで見てください。

我对Golang的重要特性——goroutine和channel很感兴趣,但目前尚未接触过。未来我希望能够攻克这些领域。

结束了。

广告
将在 10 秒后关闭
bannerAds