译者:ZephyrJung
原文:https://www.nada.kth.se/%7Esnilsson/go_for_java_programmers/
来源:为 Java 程序员而准备的 Go 指南
鉴于水平有限,未免有很多不合适之处甚至错误,欢迎各位批评指证,Github地址在这里
当前为初步版本,将进一步调整,使行文更通顺。
这篇文章是为了帮助Java程序员们迅速的掌握Go语言。
本篇将先用Java程序员耳熟能详的特性举例,然后通过Go片段给出一些相对细节的描述,最后给出一个没有直接Java代码对应的说明例子。
Hello Stack (example)
为了激发你的兴趣,我们将以一个麻雀虽小五脏俱全的典型案例开始,即Stack.java
Go语言实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // Package collection implements a generic stack. package collection // The zero value for Stack is an empty stack ready to use. type Stack struct {
data []interface{} } // Push adds x to the top of the stack. func (s *Stack) Push(x interface{}) {
s.data = append(s.data, x) } // Pop removes and returns the top element of the stack. // It’s a run-time error to call Pop on an empty stack. func (s *Stack) Pop() interface{} {
i := len(s.data) - 1
res := s.data[i]
s.data[i] = nil // to avoid memory leak
s.data = s.data[:i]
return res } // Size returns the number of elements in the stack. func (s *Stack) Size() int {
return len(s.data) } |
2、声明的名字写在type之后
3、struct类似于Java中的class,但struct中的成员不能是方法,只可以是变量
4、interface{}类似于Java中的Object。不过它被所有的Go类型实现,不仅仅是引用类型。
5、代码段(s *Stack)声明了一个方法调用者s,类似于Java中的this
6、操作符:=同时声明并初始化变量,类型通过初始化表达式的值进行推断
如下是一个Hello World程序,展示如何使用collection.Stack这个抽象数据类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package collection_test import (
collection "."
"fmt" ) func Example() {
var s collection.Stack
s.Push( "world" )
s.Push( "hello, " )
for s.Size() > 0 {
fmt.Print(s.Pop())
}
fmt.Println()
// Output: hello, world } |
概念上的区别
1、Go没有带构造器的类,实例方法,继承层次结构,动态方法查找,取而代之的是structs和interfaces。Interfaces也可以用在类似Java的泛型的地方。
2、Go提供任何类型的值的指针,不仅仅是对象和数组。对于任何类型T,都有一个对应的指针类型*T,表示该类型值的指针。
3、Go允许任意类型上的方法,无需装箱。方法的调用者(类似于Java中的this),可以是一个值或一个指针。
4、在Go中,数组属于数值。当数组被用作方法参数时,方法接收到的是一个数组的拷贝,而非指针。然而实践中,方法经常使用slices作为参数。slices是对数组的底层引用。
5、语言内置支持字符串, a string behaves like a slice of bytes, 但它是不可改变的。
6、语言内置支持哈希表,称为map
7、单独执行线程,goroutines,以及线程之间的通信渠道,channels,都被Go语言内置支持。
8、特定类型(maps,slices,channels)是通过引用而非值传递的。这就是说,想方法传递一个map类型并不是传递了map的拷贝。如果方法改变了这个map,方法外部调用者也会看到。用Java来讲,可以把这个想象成map的引用。
9、Go提供了两种访问级别,与Java的public和package private类似。名称首部为大写时代表public,否则为package-private
并没有使用exceptions,Go使用了error类型来代表注入到达文件末尾之类的事件,以及运行时panics来代表注入试图越界读取数组的运行时错误
10、Go不支持隐式类型转换。包含不同类型的表达式需要进行显式转换
11、Go不支持方法重载。函数和方法在同一作用域内必须有不同的名称
12、Go用nil代表错误的指针,类似于Java的null
声明
声明语法与Java正好相反,将类型写在名称的后面。类型声明从左往右读可能更容易点儿。

var(声明通常是以关键字后面跟随着被声明的对象名称的形式,关键字可能是const,type,var,或func。你可以用一个关键字把一系列的声明写在括号内。