从 java 到 Go

zonghsh001 · 2021-11-10 11:32:02 · 3275 次点击 · 预计阅读时间 2 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2021-11-10 11:32:02 的文章,其中的信息可能已经有所发展或是发生改变。

前言

换了一家新公司,没想到把原来用了10多年的 Java 也换没了。公司开始向 k8s 转换,需要学习 go 语言。外面又很难招到 go 的熟练工,所以招 Java 人员进来自学成才。从熟悉的领域转到陌生的领域,总有些不适感。把期间遇到的问题和需要注意的点以及些许吐槽在此记录一下。不去评判两种语言的好与坏。

go 中少得可怜的集合类

Java 中的集合类是丰富多彩的,这也造成了,初学者的选择困难症。了解得不够仔细的话,经常是随便选。而 go 中则少得可怜,原生的只有 map 、 slice (类似于 Java 中的 List) 和 array(我还没用过这种类型)。array 和 slice 的区别类似于 Java 中的数组和 list 的区别。Go 中连个 Set 都没有,用起来很不方便(当然,也有别人造好的轮子)。

go 中没有重入锁的概念

go 中一个 goroutine (类似于 Java 的线程) 获得了某个锁,如果在其随后调用的方法中,还有获得这个锁的代码,那么相当于死锁了,不像 Java 中可以重入。这点感觉不是太好。编码时要特别小心。

go 中错误处理

go 认为错误是可预见性的,所以一般会发生错误的地方(如:数据库操作,网络连接)显式地把错误当做返回值。所以有大量的地方有类似如下的代码。当一个service 里调用多个会返回 error 的方法时,会有多个下面这样处理的代码片断,感觉有点繁锁。个人还是比较喜欢 Java 的在最外层去捕捉异常的方式。

if err != nil {
   ......
}

go 的日期格式

go 中的日期格式化时,用的是: 2006-01-02 15:04:05 , 而不是 yyyy-MM-dd HH:mmss 这种比较通用的表示。有点太异类了。

go 的时间

在设置某个请求的时候,一般会设置一个超时时间, go 中专门定义了一个 duration 的类型, 如 time.Second 表示秒,一般我们会定义一个变量(如: DefaultTimeout = 10),然后设置的时候,我们想当然地认为像下面这样设置

req.SetTimeout(DefaultTimeout * time.Second)

但是很不幸,编译器直接报错了。但是像下面那样写又是可以的。WTF。

req.SetTimeout(10 * time.Second)

解决方法是:

req.SetTimeout(time.Duration(DefaultTimeout) * time.Second)

go 中几乎没有 null 值

go 中除了需要用 make 创建的类型和 interface, 其它的类型都没有 null 值,go 都会给其一个“零”值。这个从 Java 转过来的特别不习惯,主要有几下几点:

  • go 中如果要返回一个结构体, 则方法中当出现错误处理时,没办法返回一个 nil 值 ,只能返回一个空的结构体。感觉有点浪费内存 (从别人的留言中知道:空结构体不占内存。又Get 了一个知识点)。
  • 对于一些代码项,不要使用 0。比如 status 用 0 表示 disabled。如果这样做了,当你查询时, 不管你传没传 status, 得到的 status 的值就是 0,没办法区分到底要不要根据 status 进行查询

赋值顺序一定要正确

stu := new(Student)
students := make([]Student, 0)
students = append(students, stu)

teacher := new(Teacher)
teachers := make([]Teacher, 0)
teachers = append(teachers, teacher)

stu.Teachers = teachers

 这样的话,你会一头雾水地发现 students 里的stu 里的 Teachers 是空的。 WTF。 你需要把 students = append(students, stu) 这一句放到最下面才能解决问题。

###

暂时就写这些,以后碰到再加上。


有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3275 次点击  ∙  1 赞  
加入收藏 微博
16 回复  |  直到 2022-03-10 10:59:45
kuangzixian
kuangzixian · #1 · 3年之前

“go 中如果要返回一个结构体, 则方法中当出现错误处理时,没办法返回一个 nil 值 ,只能返回一个空的结构体。感觉有点浪费内存。” go语言的空结构体不占用内存啊

wn0112
wn0112 · #2 · 3年之前

总结不错, 有些感触.

这样的话,你会一头雾水地发现 students 里的stu 里的 Teachers 是空的。 WTF。 你需要把 students = append(students, stu) 这一句放到最下面才能解决问题。

这里是因你是先append() , 这是append stu 的一份拷贝, 然后又操作原 stu, students里的stu是副本, 肯定是空的嘛

liangmanlin
liangmanlin · #3 · 3年之前

10年java我估计你也是半桶水了,一百有10年经验的人,是不可能看不懂slice的,这种低级错误只有应届生才会犯错。

zonghsh001
zonghsh001 · #4 · 3年之前

@kuangzixian go 刚开始学没多久,这个学到了。

zonghsh001
zonghsh001 · #5 · 3年之前

@liangmanlin 嗯。我是半桶水。不过有人连字都打错,不知道是不是因为是整桶水的原因。另外,我没说看不懂,只是Java 中的对象都是传址,go 中除了明确用取地址符外,基本都是传值,这跟Java 有很大差别。做为 Java 转过来的,会不习惯。

kuangzixian
kuangzixian · #6 · 3年之前
zonghsh001zonghsh001 #4 回复

@kuangzixian go 刚开始学没多久,这个学到了。

哈哈,我也刚刚学Go,不过看得出楼主Java功底很好~

chenlong_
chenlong_ · #7 · 3年之前

最后一点,不知道楼主是写错了还是没有测试,new出来的是指针,往[]Student中append会报错,正确应该是往[]*Student中添加,这个时候是不存在顺序问题的

image.png

go-magic
go-magic · #8 · 3年之前

说GO没有SET估计你也不知道SET是怎么实现的吧

ws1992go
ws1992go · #9 · 3年之前

没有 Null 值是值得吐槽的。

但是太多的特性,带来的往往是眼花缭乱的实现,代码逐渐变得魔幻,不是每一个程序员都像语言的设计者一样细心,清楚语言的东西。

wln123
wln123 · #10 · 3年之前

没有集合的原因是没有泛型,泛型明年就有了,集合类也会有,还有你那个时间的问题,go中要求显式转换类型,你用常量就可以解决问题

dongxinxing
dongxinxing · #11 · 3年之前

跟我差不多,我也是10年Java,现在转GO。

yincyu
yincyu · #12 · 3年之前

java 中不同类型相乘,可以直接隐式转换吗, 比如 浮点数 float64 乘 int64 结果是 float64

gonglf
gonglf · #13 · 3年之前

这个确定是你原创的吗??我在别的地方看到一模一样的文章

zonghsh001
zonghsh001 · #14 · 3年之前

@gonglf 嗯,另外那个是博客园。我只是发到了两个地方

zonghsh001
zonghsh001 · #15 · 3年之前

@chenlong_ 刚学Go,还在不求甚解的阶段

zonghsh001
zonghsh001 · #16 · 3年之前
chenlong_chenlong_ #7 回复

最后一点,不知道楼主是写错了还是没有测试,new出来的是指针,往[]Student中append会报错,正确应该是往[]*Student中添加,这个时候是不存在顺序问题的 ![image.png](https://static.studygolang.com/211212/01f0b337dca89ccf0f6a6c03010d8100.png)

这里是写错了,因为当时在电脑上是 stu := Student{Name: "aaa"} 这样写的,因为公司没办法上外网,写文章时,重新敲代码图省事,就写成了 stu := new(Student) , 因为初学,当时对这两种方式创建还以为是一样的,其实是不一样的,所以导致文章中的这段代码是有编译问题的。

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传