在过去的几个月里,我一直在使用 Go 进行实现。
专为弱程序员设计的?
Go 非常容易学习,简单到我花了一个晚上才完成介绍,之后我已经可以高效地编写代码了。 我以前学Go的书叫
谷歌声称 Go 的简单性是它的卖点,并且该语言是为了最大程度地提高大型团队的生产力而设计的,但我对此表示怀疑。 有些功能要么缺失,要么过于详细。 这一切都是因为对开发人员缺乏信任,认为他们无法做正确的事情。 这种对简单性的渴望是语言设计者有意识的决定,为了充分理解为什么需要它,我们必须了解开发人员的动机以及他们试图在 Go 中实现的目标。
那么为什么它变得如此简单呢? 这里有几句话
这里的关键点是我们的程序员(约。:
谷歌人 )不是研究人员。 一般来说,他们都很年轻,是学完才来找我们的,也许他们学的是Java,或者C/C++,或者Python。 他们无法理解优秀的语言,但同时我们希望他们能够创建优秀的软件。 这就是为什么他们的语言应该易于理解和学习。
他应该很熟悉,大致上和C类似。 在 Google 工作的程序员很早就开始了他们的职业生涯,并且大多熟悉过程语言,特别是 C 系列。 新编程语言对快速生产力的要求意味着该语言不应该太激进。
什么? 所以 Rob Pike 基本上是说 Google 的开发人员没那么优秀,这就是为什么他们为白痴创建了一种语言(约。:愚蠢)这样他们就能够做某事。 用什么傲慢的眼光看待自己的同事? 我一直相信 Google 的开发人员都是从地球上最聪明、最优秀的人中精心挑选出来的。 他们肯定能处理更困难的事情吗?
过于简单的文物
在任何设计中,简单都是一个值得追求的目标,但试图让事情变得简单却很困难。 然而,当尝试解决(甚至表达)复杂问题时,有时需要复杂的工具。 复杂性和复杂性并不是编程语言的最佳特性,但有一个中间立场,该语言可以创建易于理解和使用的优雅抽象。
不太善于表达
由于其对简单性的承诺,Go 缺乏在其他语言中被认为是自然的结构。 乍一看这似乎是个好主意,但实际上它会导致冗长的代码。 这样做的原因应该很明显——开发人员需要轻松阅读其他人的代码,但事实上这些简化只会损害可读性。 Go 中没有缩写:要么很多,要么什么都没有。
例如,从命令行参数读取 stdin 或文件的控制台实用程序如下所示:
package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
)
func main() {
flag.Parse()
flags := flag.Args()
var text string
var scanner *bufio.Scanner
var err error
if len(flags) > 0 {
file, err := os.Open(flags[0])
if err != nil {
log.Fatal(err)
}
scanner = bufio.NewScanner(file)
} else {
scanner = bufio.NewScanner(os.Stdin)
}
for scanner.Scan() {
text += scanner.Text()
}
err = scanner.Err()
if err != nil {
log.Fatal(err)
}
fmt.Println(text)
}
尽管此代码也试图尽可能通用,但 Go 的强制冗长会妨碍,因此,解决一个简单的问题会导致大量代码。
例如,这里是同一问题的解决方案
import std.stdio, std.array, std.conv;
void main(string[] args)
{
try
{
auto source = args.length > 1 ? File(args[1], "r") : stdin;
auto text = source.byLine.join.to!(string);
writeln(text);
}
catch (Exception ex)
{
writeln(ex.msg);
}
}
现在谁更具可读性? 我会把票投给 D。他的代码更具可读性,因为他更清楚地描述了操作。 D 使用更复杂的概念(约。:
抄袭地狱
改进 Go 的一个流行建议是通用性。 这至少有助于避免不必要的代码复制以支持所有数据类型。 例如,对整数列表求和的函数只能通过为每个整数类型复制粘贴其基本函数来实现;没有其他方法:
package main
import "fmt"
func int64Sum(list []int64) (uint64) {
var result int64 = 0
for x := 0; x < len(list); x++ {
result += list[x]
}
return uint64(result)
}
func int32Sum(list []int32) (uint64) {
var result int32 = 0
for x := 0; x < len(list); x++ {
result += list[x]
}
return uint64(result)
}
func int16Sum(list []int16) (uint64) {
var result int16 = 0
for x := 0; x < len(list); x++ {
result += list[x]
}
return uint64(result)
}
func int8Sum(list []int8) (uint64) {
var result int8 = 0
for x := 0; x < len(list); x++ {
result += list[x]
}
return uint64(result)
}
func main() {
list8 := []int8 {1, 2, 3, 4, 5}
list16 := []int16{1, 2, 3, 4, 5}
list32 := []int32{1, 2, 3, 4, 5}
list64 := []int64{1, 2, 3, 4, 5}
fmt.Println(int8Sum(list8))
fmt.Println(int16Sum(list16))
fmt.Println(int32Sum(list32))
fmt.Println(int64Sum(list64))
}
这个例子甚至不适用于有符号类型。 这种做法完全违背了不重复自己的原则(
D 上的相同示例:
import std.stdio;
import std.algorithm;
void main(string[] args)
{
[1, 2, 3, 4, 5].reduce!((a, b) => a + b).writeln;
}
简单、优雅、开门见山。 这里使用的函数是 reduce
对于模板类型和谓词。 是的,这又比 Go 版本更复杂,但对于聪明的程序员来说并不难理解。 哪个示例更易于维护且易于阅读?
简单型系统旁路
我想 Go 程序员读到这篇文章一定会口吐白沫,尖叫道:“你做错了!” 好吧,还有另一种方法可以创建泛型函数和类型,但它完全破坏了类型系统!
看一下这个愚蠢的语言修复示例来解决该问题:
package main
import "fmt"
import "reflect"
func Reduce(in interface{}, memo interface{}, fn func(interface{}, interface{}) interface{}) interface{} {
val := reflect.ValueOf(in)
for i := 0; i < val.Len(); i++ {
memo = fn(val.Index(i).Interface(), memo)
}
return memo
}
func main() {
list := []int{1, 2, 3, 4, 5}
result := Reduce(list, 0, func(val interface{}, memo interface{}) interface{} {
return memo.(int) + val.(int)
})
fmt.Println(result)
}
本次实施 Reduce
是从文章借来的 interface{}
- 一场闹剧,在语言中只需要绕过打字。 这是一个空接口,所有类型都实现它,为每个人提供完全的自由。 这种编程风格非常丑陋,但这还不是全部。 像这样的杂技技巧需要使用运行时反射。 正如罗伯·派克 (Rob Pike) 在一份报告中提到的那样,他也不喜欢滥用此功能的人。
这是一个强大的工具,应谨慎使用。 除非绝对必要,否则应避免这样做。
我会采用 D 模板而不是这些废话。 怎么会有人这么说 interface{}
更具可读性甚至类型安全?
依赖管理的困境
Go 有一个内置的依赖系统,构建在流行的托管提供商之上
在提出有关此问题的解决方案的问题后,Go 开发团队创建了
习近平的文化包袱
在我看来,Go 是由那些一生都使用 C 的人和那些不想尝试新事物的人开发的。 该语言可以描述为带有额外轮子的 C(原来。:
另一个棘手的问题是 Go 是一种过程语言(就像 C 语言的无声恐怖一样)。 您最终会以一种感觉陈旧且过时的过程式风格编写代码。 我知道面向对象编程不是灵丹妙药,但如果能够将细节抽象为类型并提供封装,那就太好了。
为了您自己的利益而简单
Go 的设计很简单,并且它成功地实现了这一目标。 它是为弱程序员编写的,使用旧语言作为模板。 它配备了简单的工具来完成简单的事情。 它易于阅读且易于使用。
它非常冗长、不起眼,而且对聪明的程序员来说很糟糕。
谢谢
来源: habr.com