大红大紫的 Golang 真的是后端开发中的万能药吗?

大红大紫的 Golang 真的是后端开发中的万能药吗?,第1张

func (c *SomeClass) privateMethod() (result string) {

return “This can only be called in SomeClass”

}

func main() {

// 生成实例

someInstance := SomeClass{

PublicVariable: “hello”,

privateVariable: “world”,

}

}

复制代码

如果你用 Java 来实现上述这个例子,可能会看到冗长的 .java 类文件,例如这样。

// SomeClass.java

public SomeClass {

public String PublicVariable; // 公共变量

private String privateVariable; // 私有变量

// 构造函数

public SomeClass(String val1, String val2) {

this.PublicVariable = val1;

this.privateVariable = val2;

}

// 公共方法

public String PublicMethod() {

return “This can be called by external modules”;

}

// 私有方法

public String privateMethod() {

return “This can only be called in SomeClass”;

}

}

// Application.java

public Application {

public static void main(String[] args) {

// 生成实例

SomeClass someInstance = new SomeClass(“hello”, “world”);

}

}

复制代码

可以看到,在 Java 代码中除了容易看花眼的多层花括号以外,还充斥着大量的 publicprivatestaticthis 等修饰用的关键词,显得异常啰嗦;而 Golang 代码中则靠简单的约定,例如首字母大小写,避免了很多重复性的修饰词。当然,Java 和 Go 在类型系统上还是有一些区别的,这也导致 Go 在处理复杂问题显得有些力不从心,这是后话,后面再讨论。总之,结论就是 Go 的语法在静态类型编程语言中非常简洁。

内置并发编程

Go 语言之所以成为分布式应用的首选,除了它性能强大以外,其最主要的原因就是它天然的并发编程。这个并发编程特性主要来自于 Golang 中的协程(Goroutine)和通道(Channel)。下面是使用协程的一个例子。

func asyncTask() {

fmt.Printf(“This is an asynchronized task”)

}

func syncTask() {

fmt.Printf(“This is a synchronized task”)

}

func main() {

go asyncTask() // 异步执行,不阻塞

syncTask() // 同步执行,阻塞

go asyncTask() // 等待前面 syncTask 完成之后,再异步执行,不阻塞

}

复制代码

可以看到,关键词 go 加函数调用可以让其作为一个异步函数执行,不会阻塞后面的代码。而如果不加 go 关键词,则会被当成是同步代码执行。如果读者熟悉 JavaScript 中的 async/awaitPromise 语法,甚至是 Java、Python 中的多线程异步编程,你会发现它们跟 Go 异步编程的简单程度不是一个量级的!

异步函数,也就是协程之间的通信可以用 Go 语言特有的通道来实现。下面是关于通道的一个例子。

func longTask(signal chan int) {

// 不带参数的 for

// 相当于 while 循环

for {

// 接收 signal 通道传值

v := <- signal

// 如果接收值为 1,停止循环

if v == 1 {

break

}

time.Sleep(1 * Second)

}

}

func main() 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 {

// 声明通道

sig := make(chan int)

// 异步调用 longTask

go longTask(sig)

// 等待 1 秒钟

time.Sleep(1 * time.Second)

// 向通道 sig 传值

sig <- 1

// 然后 longTask 会接收 sig 传值,终止循环

}

复制代码

面向接口编程

Go 语言不是严格的面向对象编程(OOP),它采用的是面向接口编程(IOP),是相对于 OOP 更先进的编程模式。作为 OOP 体系的一部分,IOP 更加强调规则和约束,以及接口类型方法的约定,从而让开发人员尽可能的关注更抽象的程序逻辑,而不是在更细节的实现方式上浪费时间。很多大型项目采用的都是 IOP 的编程模式。如果想了解更多面向接口编程,请查看 “码之道” 个人技术博客的往期文章[《为什么说 TypeScript 是开发大型前端项目的必备语言》]((),其中有关于面向接口编程的详细讲解。

Go 语言跟 TypeScript 一样,也是采用鸭子类型的方式来校验接口继承。下面这个例子可以描述 Go 语言的鸭子类型特性。

// 定义 Animal 接口

interface Animal {

Eat() // 声明 Eat 方法

Move() // 声明 Move 方法

}

// ==== 定义 Dog Start ====

// 定义 Dog 类

type Dog struct {

}

// 实现 Eat 方法

func (d *Dog) Eat() {

fmt.Printf(“Eating bones”)

}

// 实现 Move 方法

func (d *Dog) Move() {

fmt.Printf(“Moving with four legs”)

}

// ==== 定义 Dog End ====

// ==== 定义 Human Start ====

// 定义 Human 类

type Human struct {

}

// 实现 Eat 方法

func (h *Human) Eat() {

fmt.Printf(“Eating rice”)

}

// 实现 Move 方法

func (h *Human) Move() {

fmt.Printf(“Moving with two legs”)

}

// ==== 定义 Human End ====

复制代码

可以看到,虽然 Go 语言可以定义接口,但跟 Java 不同的是,Go 语言中没有显示声明接口实现(Implementation)的关键词修饰语法。在 Go 语言中,如果要继承一个接口,你只需要在结构体中实现该接口声明的所有方法。这样,对于 Go 编译器来说你定义的类就相当于继承了该接口。在这个例子中,我们规定,只要既能吃(Eat)又能活动(Move)的东西就是动物(Animal)。而狗(Dog)和人(Human)恰巧都可以吃和动,因此它们都被算作动物。这种依靠实现方法匹配度的继承方式,就是鸭子类型:如果一个动物看起来像鸭子,叫起来也像鸭子,那它一定是鸭子。这种鸭子类型相对于传统 OOP 编程语言显得更灵活。但是,后面我们会讨论到,这种编程方式会带来一些麻烦。

错误处理

Go 语言的错误处理是臭名昭著的啰嗦。这里先给一个简单例子。

package main

import “fmt”

func isValid(text string) (valid bool, err error){

if text == “” {

return false, error(“text cannot be empty”)

}

return text == “valid text”, nil

}

func validateForm(form map[string]string) (res bool, err error) {

for _, text := range form {

valid, err := isValid(text)

if err != nil {

return false, err

}

if !valid {

return false, nil

}

}

return true, nil

}

func submitForm(form map[string]string) (err error) {

if res, err := validateForm(form); err != nil || !res {

return error(“submit error”)

}

fmt.Printf(“submitted”)

return nil

}

func main() {

form := map[string]string{

“field1”: “”,

“field2”: “invalid text”,

“field2”: “valid text”,

}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/801218.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-07
下一篇 2022-05-07

发表评论

登录后才能评论

评论列表(0条)

保存