MENU

【代码札记】从Java到Golang

June 21, 2020 • 瞎折腾

最近入职滴滴实习,是朋友推荐去的,所以没有经过面试。具体的工作内容还是以 Golang 居多,Python 次之,Java 基本用不上。而众所周知,我是中度 Java 重度 Kotlin 依赖,其他语言基本没咋碰过,所以我考虑入门 Golang。从入门到上手大约经过了 5 天不到,完成了一个需求,感觉还可以,遂决定在此记录一些从 Java 初入 Golang 的皮毛。

语法

语法不必多说,自然和 Java 大不相同。其中我比较喜欢的一些特性有:

  • if 等语句不需要括号
  • 语句结尾不需要分号(与 Kotlin 相同)
  • 循环只有一个 for 关键字
  • 多种方便且不会混淆的定义变量的方式

第一点不必多说,虽然加上括号感觉很规整,但是实际在敲代码的时候打完 if 还要按住 Shift 去打括号,我个人认为是一个不必要的打断。第二个也是类似的理由。第三个嘛,我觉得挺好,因为不用在 while 与 for 之前选择困难了,就一个 for,爱用不用,别的没有,也挺好。

至于第四个嘛,我想多说两句。方便是较原版 Java 说的,一个很复杂的类型要定义起来就很容易成为这个样子:

  • List<Triple<Pair<String, Map<Integer, Integer>>, string, List<Pair<String, Integer>>>> list = new ArrayList<>();

上面是一个比较极端的例子,但是就平时而言老是 intfloat 或者 ArrayList 这些定义,前后要写两次(后面的 new),就很烦。虽然 Java 后来的版本有个 var 关键字,但还是不如 Kotlin 的 varval 好用。Golang 虽然没有 val,只能是 const 而且还有限制,但是定义变量方式有很多种:

  • var x = 1
  • var y Int = 2
  • z := 3

前两种比较传统,不多说了,主要想说第三种,他真是方便啊,特别顺手,几乎大多数时候都可以用到,而且用:= 的方式来定义,没有复用 =,有效杜绝的拼写错误带来的问题(说你呢 Python),而且强类型使得在编译期间就能发现很多错误,同时代码提示也被完整的支持,不像有些语言弱类型写起来连个代码提示都没有,拿成员也贼麻烦(没错,我就是针对 Python,和 JS)。

但是 Golang 中确实也有我不喜欢的写法:

  • 字符串类似 C 的写法
  • 利用首字母大小写控制访问权限
  • 结构体和接口

字符串可以说是我一个需求中接触最多的类型,在 Java 中处理字符串很容易,直接对一个字符串对象调用成员函数就可以了。而 Golang 则需要引用一个 strings 的包,以类 C 的形式去调用,请见对比:

  • str = " hahaha ".trim(); // Java
  • str = strings.TrimSpace(" hahaha ") // Go
  • str = " 123456 ".replace("123", "321"); // Java
  • str = strings.Replace(" 123456 ", "123", "321") // Go
  • var foo = " 123,456 ";
  • foo = foo.trim().split(",")[0]; // foo = "123", Java
  • foo := " 123,456 "
  • foo = strings.Split(strings.TrimSpace(foo), ",")[0] // Go

关于第二个问题,Golang 的访问权限我觉得和 Java 相比相差甚远。前者只能控制包外能否访问,换句话说就是有无 public 修饰的区别,首字母大写就是有,首字母小写就是没有。缺乏严格类的概念使得函数之外定义的一些变量在整个包之类都能被访问,这就某种程度上带来的一些杂乱,但是好在是写 Java 的,诸如 isTheConditionInThisClassCanBeSatisfied 这样的变量名可以轻而易举的写出来,Golang 里也不叫事儿 2333

至于接口和结构体,下面就要说说 Golang 在设计上与 Java 的根本性不同了。

理念

首先 Golang 可以做到面向对象,但是又没那么的面向对象。在 Golang 中没有类的概念,对应的是结构体,与 C++ 的差不多:

  • type Book struct {
  • id int
  • isbn string
  • title string
  • }
  • func (book Book) ToString() string {
  • return fmt.Sprintf("%v %v", book.id, book.title)
  • }
  • func (book *Book) ClearTitle() {
  • book.title = ""
  • }

struct 中定义结构体的成员变量,亦可以直接包含其他结构体,被包含的结构体成员可与本结构体成员同级访问(语法糖)。而结构体的成员函数则分为两种,一种是接收者为对象的函数,这种函数的接收者是被调用者的复制,函数内对于 book 的修改不会反映到外部被调用者那里;另一种则是接收者为对象的引用,函数内会自动解引用,此时产生的修改将会反映到外部被调用者身上。这个就和 C++ 不同的传值方法有些类似。

关于接口,实际上是我觉得与 Java 相差最大的地方。

Java 以及好多语言中的接口是为函数调用提供一个标准,换言之即我不关心你是一个什么样的对象,但是你要满足这个接口定义的标准我才可以使用你。因此在 Java 实践中常常需要暴露出一个接口供其他使用者实现。而 Golang 则不一样:Golang 中并不显式的实现接口,而是通过实现方法来隐式的。这一说有点迷,实际上我也没明白 Golang 的设计者是怎么想的,但是按 Java 那么用 Golang 的接口也完全没有问题。

总之目前就是这个样子,初入 Golang,好多思想还是源于 Java,其中并发还尚未品尝到滋味,届时可能会在单独写一篇关于 Golang 并发的文章吧。这一篇诚如开头所说,只是些皮毛与基础,还未能探求到语言设计之初的一些想法。这里正好也与大家分享一下我入门 Golang 所看的视频:「Learn Go Programming - Golang Tutorial for Beginners」.

- 全文完 -


知识共享许可协议
【代码札记】从 Java 到 Golang天空 Blond 采用 知识共享 署名 - 非商业性使用 - 相同方式共享 4.0 国际 许可协议进行许可。
本许可协议授权之外的使用权限可以从 https://skyblond.info/about.html 处获得。

Archives QR Code
QR Code for this page
Tipping QR Code
Leave a Comment

4 Comments
  1. 到此一游

  2. 哇,博主已经开始实习了吗,好强。

    1. @NiceBowl 没有啊,我就是赚零花钱去的,目标是买个 switch

  3. wys wys

    祝贺祝贺,好好干!!