前一篇从语言界定、环境搭建、helloword和包结构与java做了对比,接下来就开始从go的语法上和java进行对比。
说到语法,首先需要强调的一点就是“大小写”,go和java一样都是大小写敏感的,另外有关大小写的地方就是权限相关:
Go在大小写方面它有一些默认的行为:
- 大写字母开头的变量是,是公有变量;小写字母开头的是私有变量。
- 大写字母开头的函数也是一样,相当于java中的带public关键词的公有函数;小写字母开头的相当于private关键词的私有函数。
接下来说下继续要对比学习的内容:变量、常量、还有基本数据类型。
一,变量
go中变量的定义有多种方式,以string类型为例://定义一个string类型的变量 var vname string //定义三个string类型的变量 var vname1, vname2, vname3 string //定义并初始化 var vname string = “value” //同时初始化多个变量 var vname1, vname2, vname3 string= “v1”, ”v2“, “v3” //有点繁琐?没关系,可以直接忽略类型声明(Go会根据其相应值的类型来帮你初始化它们),那么上面的代码变成这样了 var vname1, vname2, vname3 = “v1”, ”v2“, “v3” //还繁琐?好吧,继续简化,可以省略var,换成“:=”: vname1, vname2, vname3 := “v1”, ”v2“, “v3”:=这个符号直接取代了var和type,这种形式叫做简短声明。不过它只能用在函数内部;函数外部使用会报错,所以一般用var方式来定义全局变量;
变量定义在不同语言上都有自己的语法,对于java开发者来说可能感觉最不习惯的是把类型标识符放到了变量名的后面(这个真的好别扭),其他的还好,var的声明,类型自动匹配等在js上也都比较习惯了。
“_”变量,这个是go的一个特殊变量名,这个变量名表示“被丢弃的”或者“无用的”,这个其实不用太在意,知道有这么个变量就好了。需要提到的一点就是,和包类似,go的编译器对于声明了但是没有使用的变量会报错的,当然"_"除外,比如:
func main() { _, b := 1, 2 }这个时候编译器就会报b的错误,对于_则不会,之前在将helloword的时候,把未使用的包取个“_”的别名就不会报错是同一个原理。
二,常量
go中声明常量的关键字是const ,java中没有,相当于final修饰符。
//go的声明如下: const Pi = 3.1415926常量这边使用上和java没啥差别,也没有太多可说的,在go中有个特殊的常量:iota
iota,可以认为是一个可以被编译器修改的常量,通常用在枚举中。
在每一个使用const关键定义时,iota的值被重置为0,在本次const定义中,每使用一次iota,其值就会自动增加1,如:
const ( a = iota b = iota c = iota )
这样a,b,c的值分别是0,1,2,还可以简写如下:
const ( a = iota //0 b //1 c //2 )
三,基本类型
1,布尔型布尔类型当然是都有的了,和java的没啥区别,没啥好说的,简单看一下:
//java: boolean isOk=false; //go: var isOk bool //or isOk:=false
2,数值型
2.1,整型
java中的数值类型是有符号的,比如:
int a=-1,b=1;在go中,将属性类型分开了,比如int分为了int(有符号)和uint(无符号),上边的例子用go写如下:
var a int=-1 //有符号 var b uint=1 //无符号说到数值类型,就一定要说范围,我们知道,java中的int是有范围的:-2147483648 ~ 2147483647
//java: int a = -2147483648; a = 2147483647; a = 2147483648; //报错,超出范围了 //go: var a int = -2147483648 a = 2147483647 a = 2147483648 //正确通过上面的测试,你会发现go的int没有超出范围报错,是因为go的数值类型没有范围吗?
不是的,Go里面也有直接定义好位数的类型:int8, int16, rune/int32, int64 和 byte/uint8, uint16, uint32, uint64 (rune是int32的别称,byte是uint8的别称)
如下:
//go: //int 32 var a1 int32 = 2147483647 //正确 //a1 = 2147483648 //错误,超出范围 //uint32 var b1 uint32 = 2147483647*2+1 //最大范围 //b1 = 2147483647*2+2 //报错,超出范围通过上面的测试,发现int32和java中的int范围相同,而且有符号和无符号的长度相同。
那go中的int是多少位呢?go的数值类型具体长度会根据系统平台来决定,比我测试环境是64机器,那么int的范围与 int64相同(范围就和java中的long范围相同了,但不用像java中要以l结尾),如果是32位系统,则int的范围与int32相同。
说到与java类型的对应关系,java整型基本类型中还有short,在go中就相当于int16,当然go还有无符号的uint16;在java中还有byte,对应go中的int8,在go中,也有byte,和java的byte不同的是,go的byte是uint8,是无符号。
注意:虽然在64位系统中int长度和int64相同,但是仍然是两种类型,类型间不能相互转化:
var a int //32位系统 var a1 int32 var a3 rune = 10 a1=a3 //正确 a=a3 //错误不同类型不能转化,rune和int32可以,因为rune和int32是相同类型,只是有两个名称而已。
2.2,浮点型
java中的浮点型有float和double,分别是32位和64位,在java中,float的数值必须以f或F结尾,与double区分,而double的数值可以加d也可以不加
go中浮点型只有float32和float64(没有float),默认是float64,分别对应java中的float和double
2.3,复数
复数,这个在java中不支持,在golang中是支持的,有两中长度,分别是complex128(64位实数+64位虚数)和complex64(32位实数+32位虚数)
//go: var a complex64 = 5+5i fmt.Printf("Value is: %v", a) //output: (5+5i) //内置函数complex从指定的实部和虚部构建复数,内置函数real和imag用来获取复数的实部和虚部: var b complex128 = complex(-5, 5) // -5+5i fmt.Println(real(b)) // "-5" fmt.Println(imag(b)) // "5"对于复数,可能平时用到的机会比较少,用java虽然没有支持该类型,但相关的复数操作可以自己实现。
这里可以列个表,对比一下go和java中的数值类型:
类型 | Java | Golang |
---|---|---|
整型 | byte | int8 |
int | int32/rune | |
long | int64 | |
int、int16、uint、uint8/byte、uint16, uint32, uint64 | ||
浮点型 | float | float32 |
double | float64 | |
复数 | complex64、 complex128 |
3,字符串
字符串很常用,但是在java中字符串(String)不是基本类型,java中针对字符的基本类型是char,一个单一的16位Unicode字符;
在go中字符串类型(string)是基本类型,固定长度不可以改变,采用UTF-8字符集编码,用一对双引号("")或反引号(``)括起来作为定义:
//字符串初始化 var s = "hello" //多行字符使用`` s1:= `"this is a test" `学java的人都知道,java中的Stirng是不可变类,在go中,string也是不可变的,但可以采用切片的方式来修改字符串:
var s = "hello" s = "ha" + s[2:] // 字符串虽不能更改,但可进行切片操作 fmt.Printf(s) // 变成hallo
切片是go中内置的一种特殊可变数组,这个以后会说到。
欢迎指教!