Java程序员的Go语言快速入门指南

本文介绍

Go语言已成为一种流行的非常流行编程语言,它是Docker、Kubernetes、OpenShift等一些炫酷新开源项目的首选编程语言,掌握Go语言意味着我们都可以为这些开源项目做贡献。

我在日常学习中学习过很多编程语言,例如C,C++,C#,Java,Python,Scala,Groovy,Assembly,JavaScript等。我花了几周的时间学习Go语言和阅读Docker、Kubernetes、OpenShift的源代码。我认为对于一个程序员来说,学习另外一种新的编程语言,可以将你所熟悉的编程语言(例如Java)中的概念带入新的编程语言中,这对你学习新的编程语言有很大的帮助和参考意义。

本文当然不是单纯的Go语言的简介,也不是完整的Java-Go的映射。本文的目的是快速帮助Java开发人员快速的了解和入门Go语言开发。

项目结构

在Go语言项目中,通常直接将源代码放到项目的根目录中,而不是像Java那样将源码放入项目的src目录中。在项目根目录中也可以根据业务划分不同的package。

Packages

与Java类似,Go语言将其代码组织到package中。您可以通过packagepackage_name在源码的顶部来声明源文件所在的package(及其所有常量,类型,函数等);但是与Java不同,你不需要不输入完整package路径,只用输入包名即可。例如:

packageapi

所以,如果你的包名为:“api/endpoints”,那么对应文件系统上的目录结构就是“./pkg/api/endpoints”,endpoints包在源代码中声明方式如下:

packageendpoints

这点要和Java区分开,如果按照Java的包声明规则,那么声明可能就是下面这种了:

//注意这是错误的声明方式packageapi.endpoints导入Packages

Go语言和Java一样,可以通过import的方式导入package,在Go语言中导入包的方式如下:

import(stderrs"errors""time""golang.org/x/net/context""k8s.io/kubernetes/pkg/auth/user")

我们可以根据包路径中的最后一个包名称在源代码中使用包。例如在上面的示例中,我们导入了包k8s.io/kubernetes/pkg/auth/user,那么在代码中可以可以使用user.xxx调用该包下的静态方法、类、常量,例如:user.Foo()。如果我们想在源文件中重命名包,以免与其他名称冲突,那么可以使用下面这种方式:

import(stderrs"errors")

那么我们在代码中调用errors包下的程序就需要通过别名,例如:stderrs.Foo()

main包

main包是Go语言的应用程序入口点。main包中必须有一个main()函数,它没有参数和返回值:

funcmain(){…}

这个main函数就是项目的启动入口。

类型、常量、函数的的作用域

Go语言中没有类似Java中private、protected、public关键字,Go语言是通过命名的首字母大小写来定义struct/type/function/variable的作用域。首字母小写表示private、大写表示public。

例如,在foo包中,如果你有一个这样的函数funcBar(),由于“Bar”的首字母大写,因此可以在包外部调用。如果你导入foo包,则可以访问foo.Bar()。如果将函数修改为首字母小写:funcbar(),那么包外是无法访问该函数的。

函数支持多返回值

Go语言中的函数(可以理解为Java中的方法)可以有多个返回值。例如,调用返回多个值的函数如下所示:

//函数定义funcfoo()(string,bool){...}//函数调用str,ok:=foo()

其中:str和ok为foo的两个返回值。

类,结构,方法

在Java中我们有class,Go语言中是没有class的,但是有和class概念、作用相似的东西:结构体(struct)。在struct中可以定义函数和成员变量。

例如:

typeRectanglestruct{widthintheightint}

这是一个名为Rectangle的struct,具有两个字段:width和height。我们可以这样创建一个新的Rectangle:

r:=new(Rectangle)

我们可以像下面这样访问他的字段:

r.width=10r.height=5

我们可以像下面这样为结构体添加方法:

func(r*Rectangle)area()int{returnr.width*r.height}类型继承

Go语言不想Java那样有关键字extends来实现类的继承。类型的继承是匿名字段组合来完成的。如下:

typeRectanglestruct{Shapewidthintheightint}

这这个示例中,Rectangle有一个匿名字段Shape,那么Shape中的字段和方法都会在Rectangle对象中可见。

需要注意的是,如果一个函数的要求的参数是Shape,虽然Rectangle继承自Shape,也不能直接将Rectangle对象作为该函数的参数。这点是和Java不同的,Java中是允许将更具体的子类型作为参数的。如果要想实现类型的多态,请使用Go语言中的接口(下个章节会讲到)

多态、接口

在Java中,我们有特定的接口类型:interface,接口中的方法由继承了该接口的class来具体实现。Go语言同样有接口功能,但是Go语言中接口的实现是不需要显式的去声明,只需要结构体(即Java中的类)去实现接口中方法即可。

如下,有一个Shape接口,该接口中声明了函数Print()

typeShapeinterface{Print()}

当我们创建我们的结构体时,我们不用像在Java中那样通过“implements”来声明它。我们只需实现Shape接口中的方法,Go语言就会认为该结构体实现类Shape接口,例如:

typeRectanglestruct{widthintheightint}func(r*Rectangle)Print(){fmt.println("Rectangle!");}

在这种情况下,Rectangle对象可以传递给参数为Shape类型的函数了,因为Rectangle实现了Shape所有的方法。

for循环

GO语言循环例子:

fori:=1;i=10;i++{fmt.Println(i)}

当迭代数组(或者字符串、map、slice等等)时,可以使用range来进行迭代,假设foo是一个列表,那么迭代方式如下:

forv:=rangefoo{fmt.println("value="+v);}

如果你需要在迭代过程中获取数据的索引,那么可以使用以下方式:

fori,v:=rangefoo{fmt.println("index"+i+"hasvalue="+v);}while循环

Go语言中没有while循环,但是你可以使用for循环来实现while循环相同的功能,如下:

sum:=1forsum{sum+=sum}fmt.Println(sum)

下面是无限循环的例子:

for{something...}指针与引用

Java中值类型和引用类型都是隐式的,int、double、float、long、byte、short、char、boolean为值类型,其他的都是引用类型,而Go语言中却不是这样。

在Go语言中:

表示取地址,例如你有一个变量a那么a就是变量a在内存中的地址,对于Golang指针也是有类型的,比如a是一个string那么a是一个string的指针类型,在Go里面叫string。*表示取值,接上面的例子,假设你定义b:=a如果你打印b,那么输出的是a的内存地址,如果要取值,那么需要使用:*b

下面我们来看一个例子:

packagemainimport("fmt")funcmain(){a:=""b:=afmt.Println(a)fmt.Println(b)fmt.Println(*b)}输出结果为:0x40c128垃圾回收

和Java一样,Go语言是有自己的垃圾回收机制的,不需要我们显式的释放内存,垃圾回收机制能够大大的减轻开发的复杂度。

本文由码农俱乐部[1]翻译自:







































白癜风药物治疗能好吗
白癫风



转载请注明:http://www.shhjfk.com/xxzl/xxzl/9936.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了