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

    祝贺祝贺,好好干!!