关于golang:为什么-Go-用起来会难受这-6-个细节你知道吗

5次阅读

共计 2238 个字符,预计需要花费 6 分钟才能阅读完成。

大家好,我是煎鱼。

在做新的利用选型时,咱们会进行利用编程语言的抉择,这时会纠结 Java、PHP、Go… 各种,会思考有没有致命的问题,不能用?

能够明确的是,Go 没有十分致命的问题,否则你我他都不会在这里相遇,也不会大火。

好受的点,倒是有不少,明天就由煎鱼和大家一起来看看。

好受的点

泛型

在 Go1.18 以前,在所有社交媒体和调查报告上来看。Go 最好受的莫过于没有泛型,

写一个通用的办法,要不得把入参申明为 interface,要不得写 N 个不同类型的一样代码的函数,代码反复率高。

如下图:

这是 Go1.18 以前最好受的点,当初新版本尽管有了泛型,但现阶段配套规范和开源库还没齐全到位,影响还是会持续存在。

浅拷贝和泄露

在写 Go 程序时,咱们常常要用到 slice、map 等根底类型。但有一个比拟麻烦的点,就是会波及到浅拷贝。

一个不留神就会引起 BUG,如下代码:

type T struct {
    A string
    B []string}

func main() {x := T{"煎鱼", []string{"下班"}}

    y := x
    y.A = "咸鱼"
    y.B[0] = "上班"

    fmt.Println(x)
    fmt.Println(y)
}

输入后果是什么?

煎鱼到底是下班了,还是上班了?

后果如下:

{煎鱼 [ 上班]}
{咸鱼 [ 上班]}

实际上在 y := x 时,他拷贝的是指向对象的指针,这个时候 xy 的底层数据其实是一家子,天然一变动 yx 的煎鱼也就上班了。

同类型的 slice 也有 append 的泄露,以及 len、cap 的不精确问题,是比拟折腾人的。

泄露的示例:

var a []int

func f(b []int) []int {a = b[:2]
 return a
}

func main() {...}

有趣味的能够具体看《Go 切片导致内存泄露,被坑两次了!》的解析。

错误处理

在 Go 的错误处理中,许多小伙伴的好受的点分两大块。一个是大量反复的 if err != nil 的代码:

func main() {x, err := foo()
 if err != nil {// handle error}
 y, err := foo()
 if err != nil {// handle error}
 z, err := foo()
 if err != nil {// handle error}
 s, err := foo()
 if err != nil {// handle error}
}

另外一块是在异样解决中,Go 现阶段是 panic 和 recover 的模式,外部还蕴含 throw 的致命性谬误抛出,无奈拦挡,为此我也见过个别事变是因而造成的。

这是一个争议性很大的板块。

nil 接口不是 nil

咱们强行将一段 Go 程序的变量值赋为 nil,并进行 nil 与 nil 的判断。

代码如下:

func main() {var v interface{}
    v = (*int)(nil)
    fmt.Println(v == nil)
}

输入的后果是什么。是 false,还是 true,又或是抛出异样?

输入后果是 fasle,nil 可不 100% 等于 nil。

这与 interface 的外部数据结构无关,是在编程时要留神的一个细节,具体可详见《Go 面试题:Go interface 的一个“坑”及原理剖析》的解析。

垃圾回收

Go 十分简洁,垃圾回收惟一的可调节的是 GC 频率,能够通过 GOGC 变量设置初始垃圾收集器的指标百分比值。

$ GOGC=100 eddycjy

简略来讲就是,GOGC 的值设置的越大,GC 的频率越低,但每次最终所触发到 GC 的堆内存也会更大。

而后就没别的形式能够优化垃圾回收器自身了,以至于当年我还被人拿 Java 来吐槽过一遍,说 Go 必定有。

依赖治理

压轴的好受点,莫过于 Go 的依赖治理。先是从 GOPATH 时代,开源后一路水土不服,前面 rsc 间接下场支棱起来硬推。

到 2022 年,目前 Go modules 还是会存在一些让人好受的点。甚至曹大总结了《Go mod 七宗罪》,不少我在工作中也遇到和替他人解决过,十分的精辟。

援用如下 7 点:

  • Go 命令的副作用:所有 go build、go list、go test 多多少少都会拉取到墙外的资源,会很慢。
  • 形同虚设的 semver 标准:go mod 的设计,就是心愿大家在软件库公布时都要恪守规范,例如在小版本时,要放弃兼容性。但这十分理想化,事实就是常常有人不恪守。
  • 无奈应答删库:公布后的软件库,你曾经拉取了。但发布者仍然能够删除,受伤的还是本人。
  • goproxy 的实现并不对立:作者 A、作者 B、作者 C 写的几套 goproxy 外部逻辑是不完全一致的,很折腾人。
  • go get 到的 lib 版本在 go build 时被批改。
  • 版本信息扩散:导入门路是蕴含版本号 v1、v2 等信息的,一旦批改,就得大面积替换。
  • go.sum 合并抵触:大型项目上的多人保护,导致频繁抵触。

相熟把握 Go 的一个体现,那就是精通 Go modules,不然我的项目都运行的不顺利。

总结

明天咱们围绕 Go 的好受场景进行了剖析和解说,本文波及的别离是:泛型、浅拷贝和泄露、错误处理、nil 接口不是 nil、垃圾回收、依赖治理。

其中不少是常见的,也有的是无意而为之(例如:垃圾回收)。从大家的角度来看,你感觉 Go 比拟好受的点还有哪些呢?

欢送大家在评论区一起留言和交换。

文章继续更新,能够微信搜【脑子进煎鱼了】浏览,本文 GitHub github.com/eddycjy/blog 已收录,学习 Go 语言能够看 Go 学习地图和路线,欢送 Star 催更。

举荐浏览

  • 你能答对这道 Go 题目吗?超过 80% 的人都答错了 …
  • Go 返回值命名还有存在的必要吗?

参考

  • golang 有什么致命的问题吗?
  • Go mod 七宗罪
正文完
 0