简介
纯粹的JavaScript背景的Web开发人员自然会选择Node.js作为他们的后端语言。作为一个基于JavaScript的运行环境,它代表了前端开发者编码后端功能的最简单途径。不过现在,对于希望实现全栈的前端开发者来说,有很多选择。
由于它的范式和理念,Go编程语言可能不会作为首选出现在脑海中。因此,前端开发人员可能会对它望而却步,尤其是那些刚刚进入全栈开发的人。
在这篇文章中,我们将探讨这些范式和特性,以及为什么值得让Go在后端/全栈网络开发中一试。我们还将探讨一些新的模式、Go 的开发者体验,以及作为首次使用 Go 的前端开发人员应该期待什么。
Go的使用情况
所有的编程语言都是为了解决一系列的用例或解决特定的问题而创建的。Go在以效率和性能为首要考虑的领域大放异彩,因为它可以快速编译成机器代码。因此,它不需要解释器或虚拟机。
由于它的编译功能,Go代码可以很容易地部署在服务器基础设施上,并相应地在各种安装中进行更新。它还支持多种操作系统和处理器架构,这的确是一个巨大的好处。
此外,Go已经成为开源基础设施软件的首选语言,一些最大和最受欢迎的项目完全用Go编写。例如,Docker就是完全用Go编写的。
Go的另一个优点是,它让程序员对内存布局和分配有相当大的控制权--比其他垃圾收集语言的典型情况要多得多。
Go通过其运行时系统实现了垃圾收集、并发、堆栈管理等功能。自动垃圾收集使并发代码更容易编写,Go在语言设计层面解决了这个开发者的痛点,它能够正确管理分配的内存。
事实上,语言设计直接影响到使用的便利性以及我们为项目建立POC的速度。Go在这方面有一套独特的功能,旨在为高度弹性和可扩展的应用程序提供服务。
接下来,我们将探讨并发性,这是 Go 中一个非常重要且备受关注的特性--特别是对于那些习惯于 JavaScript 同步特性的开发人员来说。
并发性。Go的一个关键特性
并发性使程序能够将其执行组织成几个独立的流程,并在它们之间交流行动或活动。并发编程技术是有效利用CPU和提高应用程序性能的好方法。对于企业规模的应用程序或需要同时处理成千上万个请求的应用程序来说,这是一个必不可少的功能。
并发性是通过goroutines和channel内置于Go语言本身的核心。基本上,goroutines允许应用程序同时执行几个任务。它们是廉价、轻量级的执行线程。这使语言在吞吐量、延迟和可靠性方面具有更好的性能。
如果你尝试过在其他编程语言中实现并发,特别是JavaScript,你就会明白,这样做是相当复杂的。相比之下,催生一个goroutine就像在一个函数前添加go 关键字一样简单。让我们看看下面的一个例子。
import "fmt"
package main
func doSomething(str sting) {
for i := 1; i <= 3; i++ {
fmt.Printf("%s: %d", str, i)
}
}
func main() {
// calling this function the normal way
doSomething("Hello")
// Running it inside a go routine
go doSomething("World")
go func() {
fmt.Print("Go routines are awesome")
}()
}
//add return value for func
正如我们前面提到的,Go通过goroutine和channel的并发原语使并发编程变得简单。利用其多核处理器架构和高效内存的能力是Go代码运行当今一些最大量使用的应用程序的最大原因之一。
事实上,根据其网站,Go是为网络系统建立的,以实现先进的性能和对多核机器的充分使用。
"这意味着每一个Go程序都带有已经内置的工具,如果开发者正确利用,可以使我们编写的程序表现得更好"。
请注意,有点矛盾的是,一个程序中可能只有一个线程,但却有成千上万个goroutine。如果该线程中的任何一个goroutine阻塞了,比如说,等待用户输入,那么就会创建另一个OS线程,其余的goroutine就会被转移到新的OS线程。所有这些都是由运行时来处理的,而我们作为程序员,被从这些复杂的细节中抽象出来,因为我们有一个干净的API来工作。
当然,在一个goroutine中执行动作意味着它需要能够与其他goroutine交流。为了达到这个目的,Go提供了通道。
通道是一个管道,它允许两个同时进行的goroutine通过发送和接收值来相互交流。channel <- 语法可以用来向通道发送一个值,而<-channel 语法可以用来从通道中读取一些东西,就像这样。
package main
import "fmt"
func main() {
// make a new channel
messages := make(chan string)
go func() {
// write to channel
message <- "Hello World!"
}()
// read from channel
message := <-messages
fmt.Printf("I got the message %s", message)
}
注意,当从一个信道中读取时,我们会阻止它,直到我们得到一个消息。发送方和接收方都必须准备好;也就是说,在该通道有一个相应的接收方之前,我们不能发送。
为什么前端开发人员应该学习Go
对于Go的新手来说,创建基本的应用程序是一件轻而易举的事情,而且也同样容易上手,快速构建出一些东西。Go是这样设计的:它有非常高的编译速度,开箱即用,支持并发和垃圾收集等功能,当然,Go还有非常简单清晰的语法。
如果你习惯于面向对象的编程风格,你会在Go中找到熟悉的概念。它有结构形式的类型和方法,可以实现面向对象的编程风格。没有类型层次;Go中的方法更通用,因为它们可以为任何类型的数据定义,甚至是内置类型。
结构有方法和属性,类似于典型的面向对象编程语言中的类。比如说。
package worker
import "fmt"
type Person struct {
Name string
Age int
}
func (p *Person) Talk(phrase string) {
return fmt.Sprintf("%s says: %s", p.Name, phrase)
}
这里,Person 是一个struct 类型,有字段Name 和A``ge 。Talk 是一个定义在Person 结构上的方法,用于打印一些东西。我们可以将其作为。
person := &Person{"Vivan", 22}
person.Talk("Go is awesome")
让我们来详细介绍一下Go近年来显示出快速普及的其他原因,以及为什么寻求全栈的前端开发人员应该选择Go。
轻松的包管理
Go程序是由包构成的,包的属性允许有效管理依赖关系。Go 工具链有一个内置系统,用于管理相关包的版本集,即模块。模块在Go 1.11中引入,并从1.14 中开始准备用于生产。
要使用模块创建一个项目,请运行 [go mod init](https://golang.org/ref/mod#go-mod-init).该命令会创建一个 [go.mod](https://golang.org/ref/mod#go-get)文件,以跟踪依赖性版本。要添加、升级或降级一个依赖关系,请运行go get - 例如,go get golang.org/x/text@v0.3.5 。更多关于创建模块的信息和关于用模块管理依赖关系的其他指南,请参见 Go 官方网站。
更少的语言结构和关键字
较少的结构体和关键字意味着很容易掌握Go,并在短时间内取得成效。Go在速度和语法方面与C类似。它有大约25个关键字,使得它很容易编写,总的来说,它是一种清晰和简单的语言,使开发人员能够编写可读和可维护的代码。
这种语言确实限制了你做某些事情的方式,尽管这种对灵活性的妥协产生了更大的简单性。这可能意味着要写更多的代码,但也有明确的解决方案。Go强制要求一致性,这有助于其可读性和可维护性。
Go是有主见的,并推荐了一种实现事物的习惯性方法。这些都是直接来自Go团队基于语言设计的;Effective Go展示了其中的一些内容。它倾向于组合而不是继承,其类型系统很优雅,允许添加行为或扩展功能以适应特定的使用情况,而不需要将组件紧密耦合。
与其他语言不同的是,Go将可读性和可维护性作为首要任务。Go的制作者只在语言中添加了那些相关的功能,并没有使语言变得复杂。
例如,对标准库的更新补充是很少的,而且纳入的标准很高。创造者们认为,包含在标准库中的代码承担着巨大的持续维护成本。Go标准库受制于Go 1的兼容性承诺(阻止对API中任何缺陷的修复)和Go发布时间表。
这使得标准库中的错误修复无法快速提供给用户。因此,新的代码应该生活在标准库之外,并且可以通过 [go get](https://golang.org/cmd/go/)命令访问。这样的代码可以有自己的维护者、发布周期和兼容性保证。
注意,用户可以在godoc.org上了解包的情况并阅读其文档。
作为另一个例子来证明该语言深思熟虑的特性,当Go包中的函数名称以大写字母开头时,意味着它可以被导出,而所有小写名称的函数都不能被导出。最后,但肯定不是最不重要的,Go现在支持泛型。
默认情况下是强类型的
Go是一种静态类型的语言。编译器努力确保代码不仅能正确编译,而且还能照顾到类型转换和兼容性。这有助于防止您在动态类型语言(如 JavaScript)中面临的问题,即您只有在执行代码时才发现问题。
静态代码分析
Go在很大程度上依赖于静态代码分析。例子包括用于文档的godoc,用于代码格式化的gofmt,用于代码风格提示的golint,以及其他许多例子。静态代码分析给开发者带来了安全感,让他们在做事情时更加安心。
内建的代码测试工具
测试是任何程序都必须的,所以每次写代码时都应该在实际的函数旁边添加测试函数。Go提供了一个简单的机制,可以与代码并行编写单元测试,这使得编写测试相当容易。
该工具还提供了支持,以了解你的测试的代码覆盖率,基准测试和编写示例代码,用于生成代码文档。
要创建一个测试文件,在与你的软件包源代码相同的目录下创建一个以_test.go 结尾的新文件。在该文件中,导入testing ,并写上形式的函数。我们可以在同一目录下运行go test 。该脚本会找到测试函数,建立一个测试二进制文件,并运行它。
func TestFoo(t *testing.T) {
}
注意,Go提供了一种方法来测试你编写的包。只需使用
go test命令,您就可以测试任何*_test.go文件中编写的代码。
性能
当您开始构建生产质量的应用程序时,Go 可以很好地进行扩展。无论是小型的微服务还是大型的企业应用,Go 都能提供卓越的性能。
Go的功能有助于其整体性能水平的提高,包括并发、编译器优化、非阻塞I/O、高效的值存储机制、其运行时系统以及其他。Go没有虚拟机,而是编译成机器代码,因此程序执行速度很快。
正如我们前面提到的,Go有一个内置的垃圾收集器,可以监控和识别不再需要的被占用的内存,并释放它以重新使用。这降低了由于代码封装而产生的安全漏洞的风险,同时也提供了一个有效的内存管理。
内置的HTML模板引擎
Go带有一个内置的HTML模板引擎,可以在html/template 包中找到。语法一开始并不直观,尤其是来自前端背景的人,但它实际上很简单,可以完美地完成工作。
大型团队可以轻松支持Go应用程序
Go代码具有清晰、整洁的语法,学习起来不费吹灰之力,因此与你一起工作的开发人员可以在短短几天内学会他们所需要的一切。这也将有助于开发人员轻松支持现有的应用程序。
此外,Go有相当多的在线课程可供选择,还有很多工具可以使用,包括自动文档、静态代码分析、嵌入式测试环境、竞赛条件检测等等。
Go的另一个很好的特点是,它拒绝编译带有未使用的变量或导入的程序,用短期的便利性换取长期的构建速度和程序的清晰度。一个未使用的变量的存在可能表明了一个错误,而未使用的导入只是减慢了编译速度,随着时间的推移,程序的代码(和更多的开发者)的积累,这种影响会变得非常大。
正如你所看到的,Go给开发者和商业利益相关者带来了一大堆的好处。这也是该语言最近流行起来的原因之一。不过,Go还不是一种完美的语言。在你决定在你的项目中使用Go之前,你应该考虑它的缺点。
最后的想法
Go项目不仅仅是语言规范,也是一个工具链和一个生态系统,包括标准库和由组织和个人贡献的外部第三方库。创建该语言的核心原因是为了帮助管理大型代码库和提高开发人员的生产力。
Go在大型项目中被大量采用,由于它的工具、生态系统和语言设计,程序员们正稳步向它靠拢,尤其是为了建立大型和高度可扩展的基础设施。对于任何有经验的开发者来说,开始使用Go是很简单的,Go的主页上有从安装工具链到学习Go的所有说明。
Go也是一种简单但有主见的语言。它的自动类型推理与动态语言的类型推理相当相似,所以它为JavaScript开发人员提供了熟悉的感觉。另外,Go的自动文档允许我们自动将代码记录在与标准库和内置的API相同的质量水平上。
最后,有了强大的标准库,它在构建API/后端方面是非常棒的。Go也是跨平台的--它可以在Linux、macOS和Windows上运行--并且内置了一些有用的工具,用于代码提示、代码生成、构建、测试等等。
更多关于为什么前端开发者要选择Go的细节,请查看Go文档的FAQ页面。谢谢您!
The postGetting started with Go for frontend developersappeared first onLogRocket Blog.