首页 > 从Java角度看Golang
头像
天坑转码徐小虾
发布于 2021-08-03 15:37
+ 关注

从Java角度看Golang

前言

熟练掌握一门编程语言,再学一门新的会很容易上手,因为语言都是相通的,设计模式类似,只不过用处不大一样。所以一般学一门语言时,我都会用自己比较熟悉的语言做一个类比,辅助自己理解。

现在大多数同学学的都是Java,而Golang是一门比较热门的语言,广泛用于云原生生生态。那么这篇文章,我用Java的视角看Golang,给出一些Java和Golang的语法类比



Java和Golang的语法类比

1. 基础数据类型

Java基础数据类型有8种,int、long、short、float、double、byte、boolean、char

Golang基础数据类型有7种,整型(6种)byte、int、int8、int16、int32、int64、无符号整型(6种):uint、uint8、uint16、uint32、uint64、uintptr,浮点型(2种)float32、float64,复数类型(2种):complex64,complex128、字符:rune、字符串:string

并且Golang还有一些符合数据类型,如指针、数组,切片(类似Python),结构体(可以和C++的结构体类比,但是我把他理解成Java的类),还有并发编程的channel等

2. 赋值对比

Java:int a = 3;

Golang中:

全局变量:int a = 3,

局部变量:int a := 3,注意局部变量只能用:=声明

3.函数定义

使用Java的朋友应该很少使用“函数”这个词,因为对于Java来说,所有的“函数”都是基于“类”这个概念构建的,也就是只有在“类”中才会包含所谓的“函数”,这里的“函数”被称为“方法”。

而“函数”这个词源于面向过程的语言,所以在Golang中,“函数”和“方法”的最基本区别是:

函数不基于结构体而是基于包名调用,方法基于结构体调用。下面是一个例子,可以直观地看出方法和函数的区别:

package entity

import "fmt"

type Person struct {
    Name string
    Age int
    id string
}

// Person结构体/指针可调用的"方法",属于Person结构体
func (p *Person) Solve() {
    fmt.Println(p)
}

// 任何地方都可调用的"函数",不属于任何结构体,可通过entity.Solve调用
func Solve(p *Person) {
    fmt.Println(p)
}

func main() {
    personPoint := new(entity.Person) // 通过new方法创建结构体指针

    entity.Solve(personPoint) // 函数调用

    personPoint.Solve() // 方法调用
}
4.权限描述符

Java的权限描述符有private,public,protected,default

Golang中则是,如变量,结构体,方法等首字母大写,则其他包都可以访问,首字母小写,则不可访问

5.Java和Golang数组定义

Java:

ArrayType[] ArrayName = new ArrayType[length];
Golang:

var ArrayName[length] ArrayType = [length]ArrayType(.....)
6.指针与引用

Java中底层对指针进行了封装,我们不需要像C++一样关注指针(但是Java中引用的概念感觉和指针差不多,理解好引用的话理解指针也完全没有问题)

Golang中存在显式的指针操作,但是Golang的指针不像C那么复杂,不能进行指针运算。

7.Java中的new和Golang中的new make

Java中我们要new一个类,此时在堆内存中创建了这个对象



Golang中

(1) new和make都不是go的关键字,而是go预定义的函数。这意味着我们可以将new或者make重新定义为其他类型。比如:

func delta(new, make int) int { return make - new }
var p * int
p = new(int)
类似C++的用法。意思是,创建一个int类型变量,为int类型的新值分配并且清零一块内存空间,将内存空间的地址作为结果返回,这个结果就是指向int类型的值的指针.

(2) make返回一个变量而new返回一个变量的指针

8.Java和Golang的标准输出流

Java中是System.out.println

Golang中则是利用fmt包,可以与Java,C++进行类比

package main
import (
    "fmt"
)
func main() {
    var str string
    fmt.Scanln(&str)
    fmt.Printf("INPUT :%s\n", str);

    fmt.Println("Hello world");
}
9.Java与Golang的,面向对象编程

面向对象的四大特性:封装,继承,抽象,多态

Java编程中我们一般要先定义接口,并且把接口实现,过程比较约定俗成,代码量也比较大

Golang中给我的感觉则是更加自由,写起来更像面向过程(仅是更像),代码量比Java要少很多。我们可以用struct封装一些属性,类比Java中的类。而Golang中的接口不是需要像Java中先定义再实现,一般项目中是通过模块分层,实现一个接口层

10.Java与Golang的多线程

Java中线程可以继承Thread,实现Runnalbe接口,或者实现Callable接口,或者从线程池创建。Java 语言里解决并发问题靠的是多线程,但线程是个重量级的对象,不能频繁创建、销毁,而且线程切换的成本也很高,为了解决这些问题,Java SDK 提供了线程池。然而用好线程池并不容易,Java 围绕线程池提供了很多工具类,这些工具类学起来也不容易。那有没有更好的解决方案呢?Java 语言里目前还没有,但是其他语言里有,这个方案就是协程(Coroutine)。

我们可以把协程简单地理解为一种轻量级的线程。从操作系统的角度来看,线程是在内核态中调度的,而协程是在用户态调度的,所以相对于线程来说,协程切换的成本更低。协程虽然也有自己的栈,但是相比线程栈要小得多,典型的线程栈大小差不多有 1M,而协程栈的大小往往只有几 K 或者几十 K。所以,无论是从时间维度还是空间维度来看,协程都比线程轻量得多。

Golang中使用的就是协程了,在 Golang 中创建协程非常简单,在下面的示例代码中,要让 hello() 方法在一个新的协程中执行,只需要go hello("World") 这一行代码就搞定了。你可以对比着想想在 Java 里是如何“辛勤”地创建线程和线程池的吧,我的感觉一直都是:每次写完 Golang 的代码,就再也不想写 Java 代码了。


import (
    "fmt"
    "time"
)
func hello(msg string) {
    fmt.Println("Hello " + msg)
}
func main() {
    // 在新的协程中执行 hello 方法
    go hello("World")
    fmt.Println("Run in main")
    // 等待 100 毫秒让协程执行结束
    time.Sleep(100 * time.Millisecond)
}


总结

总结以上就是学习和使用过程中的一些简单对比,可能还有不正确,不深入的地方,随着学习的深入也会不断更新

Golang现在也是一门很有发展的语言,大家感兴趣可以学习一波~



粉丝福利:
公众号∶天坑转码小助手

如果你想省去自己搜集面经花费的大量时间,

后台回复【面经】获取近百家公司的面经集合



如果你想获得全程1对1的辅导项目,

后台回复【辅导】,帮助你不走弯路,尽快转行上岸!

全部评论

(0) 回帖
加载中...
话题 回帖

相关热帖

近期精华帖

热门推荐