您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 咨询培训 > Java程序员快速入门 go 语言
英文原文:GoforJavaprogrammers这篇文章帮助Java程序员快速入门Go语言。本文将以一个有代表性的例子为开始,以此让Java程序员对Go语言有个初步认识,随后将详细的描述Go语言的各个构成模块,最后以一个例子来讲解Go语言与Java语言的不同点。先来认识堆栈(例子)01//实现堆栈的包集合02packagecollection0304//生成空堆栈05typeStackstruct{06data[]interface{}07}0809//压栈顶10func(s*Stack)Push(xinterface{}){11s.data=append(s.data,x)12}1314//弹栈顶,并删除栈顶15//如果是空栈将会引发运行时错误16func(s*Stack)Pop()interface{}{17i:=len(s.data)-118res:=s.data[i]19s.data[i]=nil//toavoidmemoryleak20s.data=s.data[:i]21returnres22}2324//返回栈大小25func(s*Stack)Size()int{26returnlen(s.data)27}用纯文本在声明语句上方添加注释。申明的名字写在类型的后面。结构体和Java中类相对应,但结构体的成员只能是变量,不能是方法。interface{}类型对应Java中的Object。它不仅能代表引用类型,同时也能实现Go语言的所有类型。(s*Stack)表示申明一个方法,s对应于Java中方法隐式传的this参数。操作符:=表示申明和初始化一个变量,其类型由初始化语句决定。下面是是使用collection.Stackabstract数据类型的简单例子。01packagecollection_test0203import(04collection.05fmt06)0708funcExample(){09varscollection.Stack10s.Push(world)11s.Push(hello,)12fors.Size()0{13fmt.Print(s.Pop())14}15fmt.Println()16//Output:hello,world17}将测试包packagecolloection_test和collectionpackage放在同一目录。第一个import声明“.”表示将要用当前路径中的包并同时命名为collection,“fmt”是标准库的包名,没有重新命名,所以就直接用包名fmt即可。概念上的不同点Go没有类的构造器。Go提供结构体和接口,类的继承以及动态方法查询来进行实例化,而非通过实例方法。接口同样用于Java中的泛型。Go中不仅对象和数组可以有指向数据的指针,其它所有类型都有。对于任何类型T,都有一个指针类型*T与之相对应,其表明指向类型为T的值。Go允许在任何类型上创建方法;方法的接收者,就是Java中this,可以是个值或是指针。数组在Go中是一些值。当数组作为函数参数传递时,函数将收到数组值的拷贝,不是指针。然而实际中,经常用slices作为参数;因为切片中有数组的引用。Go中提供字串类型;字串就像是由比特序列构成的slices,但字串是不可变的。在Go中哈希表叫maps。Go提过channels类型来在多线程,goroutines之间通信来实现并发。一般类型(maps,slices,channels)传参是引用,不是值。如果传参map,参数不是对map的值拷贝;如果函数里改变了map的值,函数调用者的map也将改变。这个和Java中map类似。Go中访问权限有两种,和Java中public和包private类似。如果声明的名称首字母大写就是public,否则就是包private。Go用error类型取代Java中的异常,诸如访问文件到结尾、运行时刻panic,数组越界等等。Go不支持隐式类型转换,必须是显式的。Go不支持覆盖。函数名和方法名在同一作用域必须不同。Go用nil表示空指针,而Java用null。语法声明声明的语法同Java比较是逆向的。你写上名字然后再跟着写类型。从左至右的类型声明也许读起来容易些。Go约相等的Java写法varv1intintv1=0;varv2*intIntegerv2=null;varv3stringStringv3=;varv4[10]intint[]v4=newint[10];//v4isavalueinGo.varv5[]intint[]v5=null;varv6*struct{aint}Cv6=null;//Given:classC{inta;}varv7map[string]intHashMapString,Integerv7=null;varv8func(aint)intFv8=null;//interfaceF{intf(inta);}声明一般是采用一个关键字后面跟着被定义对象的名称,这种形式。关键字是const、type、var或者func其中之一。你也可以使用一个关键字后面跟着放在括号之中的一系列声明,这种形式。01var(02nint03xfloat6404)当声明函数时,你必须为每个参数提供一个名称,或者不为任何参数提供名称;你不能省略一些参数的名称并提供其它参数的名称。你可以用相同的类型来组织几个名字,例如:01funcf(i,j,kint,s,tstring)一个变量可以在声明它时初始化值。进行此操作时,可以指定变量的类型,但这并非必需的。当不指定类型时,则默认为初始化表达式的类型。01varv9=*v2如果一个变量没有明确地初始化,则必须指定其类型。在这种情况下,它将隐式地初始化为其类型的零值(0,nil等)。在Go语言中没有其它某些语言中的未初始化的变量。短声明在函数内,可以用:=进行短声明,比如:01v10:=v1它等效于:01varv10=v1函数类型在Go语言中,函数是一等公民。Go的函数类型表示有相同的参数和结果类型的所有函数的集合。01typebinOpfunc(int,int)int0203varopbinOp04add:=func(i,jint)int{returni+j}0506op=add07n=op(100,200)//n=100+200多重赋值Go允许多重赋值。右边的表达式先被求值然后赋给左边的操作数。01i,j=j,i//交换i和j的值(不用象传统语言中需要第三个临时变量).函数可以有多个返回值,用参数括号后面的一个括号中的列表表示。返回值通过赋予一个变量列表来存储,如:01funcf()(iint,pj*int){...}02v1,v2=f()空标识符空标识符用下划线字符表示,它提供了一种方法来忽略由多值表达式返回的某个值,如:01v1,_=f()//忽略f()返回的第二个值.分号和格式不需要担心分号和格式,你可以用gofmt程序创建一个标准的Go样式。虽然这个样式最初看起来或许有点古怪,但它同任何其它样式一样的好,而且熟悉以后会感觉越来越舒服。在实践中Go代码使用分号不多。严格说,所有的Go语句都是由分号终止。不过,Go在非空白行的末尾隐式插入一个分号,除非该行明显未结束。这带来的影响是,在某些情况下Go不允许换行符。例如,你不能这么写01funcg()02{//INVALID;{shouldbeonpreviousline.03}g()后面会插入一个分号,使它成为一个函数声明,而不是函数定义。类似的,你也不能写01ifn==0{02}03else{//INVALID;else{shouldbeonpreviousline.04}}后面else前面会插入一个分号,导致语法错误。条件语句Go不使用括号来包裹if语句中的条件,和for语句中的表达式,以及switch语句中的值。但另一方面,它必须用花括号来包裹if或for的执行语句体。01ifab{f()}02if(ab){f()}//不需要括号.03if(ab)f()//非法(执行体未用花括号括起来)04fori=0;i10;i++{}05for(i=0;i10;i++){}//非法(表达式不需要括起来)此外,if和switch接受一个可选的初始化语句,通常用它建立一个局部变量,如:01iferr:=file.Chmod(0664);err!=nil{02log.Print(err)03returnerr04}For语句Go不具有while语句,也没有do-while语句。可以赋以for语句一个单一条件,使其与while语句等效。完全省略条件会制造一个无限循环。for语句可能包含一个范围条件,对strings,arrays,slices,maps,或channels进行迭代。除了这么写01fori:=0;ilen(a);i++{...}要循环遍历a的元素,我们也可以这么写01fori,v:=rangea{...}这会将i作为索引,给v赋以一个array,slice,或string中的连续元素。对于字符串,i是对单一字节的索引,v是一个符文类型的Unicode代码点(符文是int32的一个别名)。对maps迭代会产生键值对,而对channels则只会产生一个迭代值。Break和Continue像Java一样,Go允许使用break和continue来指定标签(label),但是这个标签所引用的必须是一个for、switch或者select语句。Switch语句在一个switch语句中,case标签默认不会往下传递(fallthrough,也就是在没有break的情况下也不会执行后续case的程序),但是你能够通过使用一个向下传递(fallthrough)语句来使得它们可以向下传递。01switchn{02case0://emptycasebody03case1:04f()//fisnotcalledwhenn==0.05}但是一个case能够有多个值:01switchn{02case0,1:03f()//fiscalledifn==0||n==1.04}case后面的值可以是支持相等比较(equalitycomparison)操作符的任何类型,比如string或者pointer。缺省的switch表达式等效于true表达式:01switch{02casen0:03f1()04casen==0:05f2()06default:07f3()08}++和--语句++和--只能被用作语句中的后缀操作符,而不能用在表达式中。例如,你不能再这样写了:n=i++。defer语句defer语句用来调用一个函数,但将其执行延迟到上一个附近的函数返回之后的时刻。被延迟的函数的执行与附近函数返回采取的路径无关。然而,当defer语句执行时,被延迟函数的参数已经被计算并保存以供之后使用。01f,err:=os.Open(filename)02deferf.Close()//当上个函数返回后,f会被关闭.常量在Go中常量可以是无类型的。这适用于数值常量,只使用无类型常量的表达式,以及没有给出类型和初始化表达式是无类型的常量声明。当一个无类型的常量被用于一个需要类型化的值的环境中,它的值会转换成类型化的。所以即使Go没有隐式的类型转换,这也能允许常量被相对自由地使用。01varauint02f(a+1)//无类型的数字常量1成为uint类型.03f(a+1e3)//1e3也作为uint类型.语言在无类型的数值常数的大小上不强加任何限制。只有当一个常数被用在需要一个有类型的值时才会根据该类型对大小有所限制,如:01consthuge=110002varnint=huge98如果在一个类型声明中类型关键字缺失,而相关的表达式计算出来是一个非类型(untyped)的数字常量,这个常量就会被分别转换成rune、int、float64、或者complex128类型,取决于这个值是否是一个字符(c
本文标题:Java程序员快速入门 go 语言
链接地址:https://www.777doc.com/doc-3550493 .html