Go基础知识点快速掌握(从Java转到Go)

310 阅读9分钟

前言

由于Java太卷,所以打算换一条赛道。最近听闻Go很火,而且就业层面上也不是很卷,所以,打算先学一学。

本人大学期间学过C、C++、Java、Python,发现这些语言当中有很多共性,因此,在学习Go的时候利用这些共性以进行快速的掌握。

本篇文章虽然叫Go基础知识点快速掌握(从Java转到Go)但实际上对于掌握了Python和C++的读者一样适用。

本篇文章会快速介绍Go的命名规则、变量常量定义、数据类型、程序结构、输入输出、运算符、函数。其他部分还请读者慢慢研究。

程序结构

和C++以及Java一样,Go的运行依托于主函数,一个程序有且只能有一个主函数(main函数)。程序从主函数开始执行。但是Go要求主函数所在的文件必须位于main包下。

Go中的包就是一个文件夹,一个文件夹就是一个包,但包名可以不和文件夹相同,举例: 以src/a/a.go这个文件为例:

package main
import "fmt"
func main(){
    fmt.Println("src/a")
}

我们将a.go文件放在了a文件夹中,但是代码中制定了包为main包(package main语句),因此,a这个文件夹就相当于是main包。而主函数在main包下,因此是可以运行的。

如果我们指定一个文件夹为某个包,那么这个文件夹下所有的文件都必须是这个包下的。比如我们这里指定了文件夹a为main包,a下所有的文件都是main包下的,不能再使用package指定一个新包。

当然,不推荐这么做,最好文件夹名和包名一致。

数据类型

Go的数据类型分为:基本数据类型和引用数据类型,和Java类似。但是,在Java中,数组是一种引用类型,但在Go中,数组是基本数据类型。

部分基本数据类型如下:

整型(int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64)

浮点型(float32、float64)

复数(complex64、complex128)

字符(byte、rune)

其中,整型的int和uint所占用的空间根据平台决定(32位占4字节,64位占8字节)。其他类型所占用的空间都写在名字上了,就不强调了。(int8就表示占8整形也就是1字节)

字符类型比较特殊,byte类型存储一个UTF-8字符,rune类型存储一个Unicode字符。

命名规则

Go是一种区分大小写的语言。Go中规定,可以使用数字、字母、下划线作为变量名,但数字不能开头(和C一样)。Go中还规定,开头字母大写代表public可见性(在其他包中可以被使用),开头字母小写代表default可见性(只能在同一个包或者同一个类中使用)。采用驼峰命名法命名。

变量定义

Go的变量定义结合了很多编程语言的特点,但基本上有以下几个部分:

  • 定义变量关键字
  • 变量名
  • 类型
  • 初始值

我们看一下语法:

var 变量名 类型 //声明一个指定类型的变量,初始值为默认值
var 变量名 类型 = 值 //声明一个指定类型的变量,初始值为给定的值
var 变量名 = 初始值 //定义一个带有初始值的变量,变量类型取决于初始值的类型
变量名 := 初始值 //声明并定义一个变量,变量类型取决于初始值,只能在函数中使用
var 变量1,变量2,... 类型 //声明若干个指定类型的变量,初始值为默认值
var 变量1,变量2,... =初始值1,初始值2,... //定义若干个带有初始值的变量,变量类型取决于初始值的类型
变量1,变量2,...:=初始值1,初始值2,... //声明并定义若干变量,变量类型取决于初始值,只能在函数中使用
var _=值 //匿名变量,表示值被舍弃,因此无法进行调用

由于Go支持多个变量赋值,因此,交换变量就比较简单: (要将代码放入主函数中运行,下同)

var a,b int=10,20
b,a=a,b
fmt.Print(a,b)

运行结果:

image.png

常量

const 常量名 类型 = 初始值就定义了一个常量,常量必须初始化。类型可以省略。

Go中提供了iota关键字用于为常量赋值。常用于构造枚举类型。

const(
    MALE = iota
    FEMALE
)

在上面这个例子中,使用iota关键字为枚举常量确定了数值,其中MALE为0,FEMALE为1,如果不适用iota关键字则需要这么做:

const(
    MALE = 0
    FEMALE = 1
)

当常量数量足够多时,iota的重要性就凸显出来了。

类型转换

语法上使用Python的类型转换语法。

类型(变量)

这种方式允许数字之间的转换,对于字符串来说是不能这样转换的,而对于结构体,则需要看情况。这一点暂且不讨论。

字符串想要转成整数或者将整数转换为字符串可以通过strconv包下的Itoa和Atoi函数来完成。

strconv.Atoi(a) //字符串转整数
strconv.itoa(a) //整数转字符串
strconv.ParseInt(a,10,32)//将字符串转为10进制整数,位数为32位,返回int64
strconv.ParseFloat(a,32)//将字符串转为小数,二进制位数为32位,返回float64
strconv.ParseComplex(a,64)//将字符串转为复数,二进制位数为64位,返回complex128
strconv.FormatFloat(a,'f',2,64)//将小数转换为2位小数的字符串,a的位数为64位(四舍五入),返回字符串

程序结构

和大部分语言一样,Go有三种程序结构:顺序结构、选择结构、循环结构。

选择结构

使用if关键字,也可以和else和else if连用。与Java不同的地方是,if后面的条件不需要有圆括号。

if age>30{
  fmt.Print("而立")
}else{
  fmt.Print("其他")
}

使用方法和其它语言一样,不多说了。需要注意一点,Go中,花括号不能单成一行。

switch关键字用起来也很舒爽,默认只执行符合条件的case。只有使用fallthrough关键字才进行穿透。

//switch方式1-正常模式
switch 条件{
  case 1:...
case 2:...
}
//switch方式2-判断类型
switch 条件{
  case string:...
case int:...
}
//switch方式3-穿透
switch 条件{
  case 1:... fallthrough
case 2:...
}
//switch方式4-传统阻断
switch 条件{
  case 1:... break
case 2:...
}
//switch方式5-复杂判断(与Java 21类似)
switch {
  case a<5:... break
case a>=5 && a<10:...
}

也允许使用default关键字作为默认情况。

循环结构

Go的循环只有for。下面是它的用法:

//方式1:无限循环
for{
...
}
//方式2:正常循环
for i:=1;i<10;i++{
  ...
}
//方式3:foreach
for index,value := range arr{
  ...
}
//方式4:充当while
for i<10{
  ...
}

输入输出

使用fmt模块中的函数可以完成输入和输出的功能。输入使用方法和C语言中的scanf一致、输出可以像Java那样输出并换行也可以像C一样使用占位符格式化输出。

package main //想让文件运行,必须规定该文件属于main包下
import "fmt"
func main(){
  var a,b int
  fmt.Scanf("%d %d",&a,&b)
  fmt.Println(a,b)
  fmt.Printf("%4d",a+b)
}

结果:

image.png

输入14和25,第六行执行时输出效果见上图第二行,第七行执行时输出效果见上图第三行。

占位符也和C一样。特别地:%T表示该变量的类型,%t表示布尔值,%p表示指针指向的地址,%v表示按照值的默认形式输出。%+v与%v类似,但输出结构体时显示字段名。%q表示Go语法字符字面值。%x和%X也可以对字符串做占位

对于多个Scanf的连用需要注意,设置占位符时需要以\n结尾,否则回车符会顺延到下一个Scanf处

package main //想让文件运行,必须规定该文件属于main包下
import "fmt"
func main(){
  var a,b,c int
  fmt.Scanf("%d %d",&a,&b)
  fmt.Scanf("%d",&c)
  fmt.Println(a,b,c)
}

运行结果:

image.png

第六行的Scanf根本就没有执行,因为第五行的回车没有处理,跑到第六行的Scanf中。

运算符

GO拥有和其他编程语言一样的运算符,因此这里不过多赘述。

但是需要注意,GO中的++和--只有一种用法:那就是标识符++或者标识符--,不会像其他编程语言那样有i++++i的区别。

其次,GO中的|&只表示按位或和按位与,并不会表示不短路逻辑或和不短路逻辑与。

GO语言中有指针的概念,和C的指针概念很像。其中&符号表示取地址,*表示取内容。

函数

和Java中的方法差不多,也有固定参数和可变参数。对于可变参数与Java一样必须放在参数表的最后。

语法:

func 函数名(参数列表) [返回值类型]{
    函数体
}

函数名遵循命名规则,参数列表的定义方式也和变量定义方式一样(参数名 类型),多个同类型参数可以在一起定义(a,b int)。定义时,函数返回值类型可以留空表示该函数没有返回值。

与Java不同的是,Go中的函数可以返回多个返回值且类型可以不同,同时也支持将函数作为参数和返回值。定义多返回值时应用()将返回值类型包裹。调用包含多返回值的函数时应为每一个返回值设置一个变量。如果有某个返回值不想使用,需要使用匿名变量接受返回值。

举例:

func A() (int,string){
    return 1,"2"
}
func main(){
    var n,s=A() //两个返回值都要
    var _,s2=A() //只要string类型的返回值
    var n2,_=A() //只要int类型的返回值
}

refer函数是一种特殊的函数,其会在函数中其他语句执行完毕后逆序执行。但传参的过程却先进行。