1. 认识HelloWorld

在前面的《Go的安装和使用》这篇文章中已经写过HelloWorld.go了,现在就来逐行认识一下它。

  1. package main
  2. import "fmt"
  3. func main() {
  4. fmt.Println("Hello, World!")
  5. }

第1行:我们的Go程序是由——package构成的,包的声明形式为:package <包名>。该行的意思是:当前HelloWorld.go文件属于main包。

第2行:如果你使用过Java或Python,那你对import肯定不陌生。该行的意思是:导入一个名为fmt的包。如果需要导入多个包,有两种写法:

  1. import "fmt"
  2. import "math"

或者使用分组形式同时导入多个包

  1. import (
  2. "fmt"
  3. "math/rand"
  4. )

显然第二种使用括号,以分组的形式导入更加方便。

第3行:我们使用func关键字来声明一个函数,在这个例子中,我们声明的是main函数。如果你有过其他语言的编程经验,肯定熟悉main函数的作用:程序的入口。

第4行:我们的函数内容放在函数的{}中,在该例中,调用了fmt包中的打印方法,由此可见,Golang语言调用函数的方法和Java、Python一样使用小数点:<包名>.<函数名>

看完这几行简单代码,我们发现:在Go语言中,并不需要分号;来结束语句。

2. 变量

2.1. 命名规范

Go语言要求标识符以一个字母或下划线开头,后面可以跟任意数量的字母、数字、下划线。不能使用关键字作为标识符

区分大小写,变量num和变量Num是两个变量。

2.2. 声明

Go语言的变量声明方式和其他语言(如C、Java、Python)不太一样。

比如,我们声明一个为int类型的变量a:

  1. var a int

可以看出,Go语言声明变量的方式为:

  1. var <变量名> <变量类型>

我们还可以同时声明多个类型相同的变量:

  1. var <变量名1>, <变量名2>, <变量名3>, ... <变量类型>

使用分组同时声明多个类型不同的变量:

  1. var (
  2. <变量名1> <变量类型1>
  3. <变量名2> <变量类型2>
  4. <变量名3> <变量类型3>
  5. ...
  6. )

下面是一个具体的例子:

  1. package main
  2. import "fmt"
  3. var i bool//类型在后
  4. func main() {
  5. var a, b, c int//多个
  6. fmt.Println(i, a, b, c)
  7. }

2.3. 初始化

当我们声明变量时,可以对其进行初始化。当有初始值时,我们可以省略变量的类型,变量会根据对应的初始值获取正确的类型。见下例:

  1. package main
  2. import "fmt"
  3. var a int = 1
  4. var b, c bool = true, false
  5. func main() {
  6. var i, j, k = 2, false, "行小观" //省略变量类型
  7. fmt.Println(a, b, c, i, j, k)
  8. k = "行小观2号" //赋值操作
  9. fmt.Println(k)
  10. }

若我们在声明变量时,不给变量赋初始值,则这些变量会被赋予“零值”。

这些零值为:

  1. 数值类型为0
  2. 布尔类型为false
  3. 字符串为""(即空字符串)

如果上例中的代码中的变量不进行初始化,即:

  1. package main
  2. import "fmt"
  3. var a int
  4. var b, c bool
  5. func main() {
  6. var i int
  7. var j bool
  8. var k string
  9. fmt.Println(a, b, c, i, j, k)
  10. }

则打印结果为:0 false false 0 false (变量k由于是空字符串,所以打印出来了但是看不到)

2.4. 短变量声明

前面介绍了当我们声明变量时有以下几种方式:

  1. var i int //声明一个int变量
  2. var i, j, k int //同时声明多个int变量
  3. var i int = 1 //声明一个int变量并初始化
  4. var i, j, k int = 1, 2, 3 //同时声明多个int变量并分别初始化
  5. var i = 1 //省略类型,声明一个int变量并初始化
  6. var i, j, k = 1, 2, 3 //省略类型,同时声明多个int变量并分别初始化

除此之外还有一种更简洁的声明变量的方式:

  1. i := 1
  2. i, j, k := 1, 2, 3

当我们使用:=声明变量时,不用写var也不用写类型,但是这种方式只能在函数内部使用,不能在函数外部使用。当在函数外部声明变量时,只能使用var

  1. package main
  2. import "fmt"
  3. var a int = 1 //函数外部
  4. func main() {
  5. var i, j int = 2, 3 //函数内部
  6. k := 4 //只能在函数中使用
  7. v1, v2, v3 := true, false, "行小观"
  8. fmt.Println(a, i, j, k, v1, v2, v3)
  9. }

此外,我们声明的变量必须要使用,如果声明了变量,但是没使用,会在编译时报错。比如:

  1. package main
  2. import "fmt"
  3. func main() {
  4. var i bool
  5. var j int //声明了,但没使用,会报错
  6. fmt.Println(i)
  7. }

对于我们导入的包也有此要求,即:导入的包必须使用。

3. 数据类型

3.1. 布尔类型

布尔类型为bool,值可取truefalse,默认值为false

3.2. 字符串类型

字符串类型为string,默认为空字符串""

3.3. 数值类型

整数类型分为:

  • 有符号数:intint8int16int32 (rune)int64

  • 无符号数:uintuint8 (byte)uint16uint32uint64

其中intuint的两种类型的长度相同,取决于具体的编译器,比如在32位系统上通常为32位,在64位系统上通常为64位。

int8uint8这些类型则是Go语言直接定义好位数的类型。runebyteint32uint8的别名。

当我们需要使用整数时,应当尽量使用int类型。当然,如果你有特殊的理由使用其他整数类型,便另当他论。

浮点数类型有两种:float32float64,注意没有所谓的float类型。

复数类型也有两种:complex64complex128

注意:不同类型的变量之间不能直接进行赋值或其他运算(比如加减乘除)

  1. package main
  2. import "fmt"
  3. var (
  4. a int = 1
  5. b int8 = 2
  6. c int16
  7. )
  8. func main() {
  9. c = b //不同类型之间进行赋值操作,[报错1]
  10. d := a + b //不同类型之间进行相加运算,[报错2]
  11. fmt.Printf("c = %v, d = %v", c, d)
  12. }

以上代码在编译过程中会报错:

[报错1]:cannot use b (type int8) as type int16 in assignment

[报错2]:invalid operation: a + b (mismatched types int and int8)

3.4. 类型转换

前面一节说过:不同类型的变量之间不能直接进行赋值或其他运算,所以我们可以间接地做。

比如:将int8类型转换为int类型,这样就可以间接地进行赋值和其他运算。

使用表达式T(v)将变量v的值的类型转换为T。注意是转换的是变量的值,变量本身的类型不变。

  1. package main
  2. import "fmt"
  3. var (
  4. a int = 1
  5. b int8 = 2
  6. c uint
  7. d int64
  8. )
  9. func main() {
  10. c = uint(b) //将变量b的值2的类型从int8转换为uint
  11. d = int64(a) + int64(b)
  12. fmt.Printf("c(%T):%v = b(%T):%v\n", c, c, b, b)
  13. fmt.Printf("a(%T):%v + b(%T):%v = d(%T):%v\n", a, a, b, b, d, d)
  14. }

注意:Go语言中的类型转换是显示的,表达式T()是必须的,不能省略。

4. 常量

常量是固定的值,值在程序运行期间不会改变。

常量可以定义为数值、字符串、布尔类型

常量的声明方式和变量差不多,区别在于常量需要用const关键字修饰,不能使用:=进行声明。

  1. package main
  2. import "fmt"
  3. const num int = 555
  4. var a int = 1
  5. func main() {
  6. const world = "世界"
  7. const truth = true
  8. fmt.Println("Hello,", world)
  9. fmt.Println("num = ", num)
  10. fmt.Println("a = ", a)
  11. fmt.Println("对吗?", truth)
  12. }

5. 初识函数

如果你之前学习过C或者Java等语言,肯定已经对函数(方法)有了一定的认识。

简单地来说,函数是对能完成某个功能的部分代码的抽象。当以后再需要该功能,我们只需要调用其对用的函数即可,不必再重复编写代码。

5.1. 函数的声明

我们在前面的内容已经使用到了函数,即main()。我们使用func关键字声明函数。

  1. func func_name() {
  2. }

5.2. 函数的参数

Go语言中,函数可以有0个或多个参数。

  1. package main
  2. import "fmt"
  3. func printName(name string, age int) {
  4. fmt.Println("我叫", name, ", 今年", age, "岁了")
  5. }
  6. func sayHello() {
  7. fmt.Println("行小观说:“你好”")
  8. }
  9. func main() {
  10. printName("行小观", 1)
  11. sayHello()
  12. }

如果你有多个参数的类型相同,你可以进行简写,只需要在这几个相同的参数最后写一遍类型即可。

  1. func foo(x int, y int, z int)
  2. 可以简写为:
  3. func foo(x, y, x int)

5.3. 函数的类型和返回值

函数的类型在函数名之后。(尽快适应Go的这种风格:类型在变量名后)

  1. package main
  2. import "fmt"
  3. func add(x int, y int) int {
  4. return x + y
  5. }
  6. func main() {
  7. fmt.Println(add(1, 2))
  8. }

当函数没有返回值时,不需要写函数的类型:

  1. func sayHello() {//没有返回值,不写函数类型
  2. fmt.Println("行小观说:“你好”")
  3. }

函数可以有0个或多个返回值

多个返回值就意味着该函数有多个返回值类型:

  1. package main
  2. import "fmt"
  3. func sumAndDiff(x, y int) (int, int) { //两个返回值类型
  4. sum := x + y
  5. diff := x - y
  6. return sum, diff //两个返回值
  7. }
  8. func main() {
  9. a, b := sumAndDiff(5, 1)
  10. fmt.Println(a, b)
  11. }

注意:和参数不同,有几个返回值就写几个返回值类型,不能简写。

Go语言还提供了另一种函数返回的方式:命名返回值。

顾名思义,我们通过给返回值进行命名,使用空return语句,这样会直接返回已命名的返回值。如上例的sumAndDiff函数可以写为:

  1. func sumAndDiff(x, y int) (sum int, diff int) {//提前命名返回值
  2. sum = x + y
  3. diff = x - y //返回值在函数中被初始化
  4. return //返回值已经初始化了,不需要再在return语句中写变量了
  5. }

下面总结一下函数的使用:

  1. func functionName(input1, input11 type1, input2 type2 ...) (type1, type11, type2 ...){
  2. //函数体
  3. return value1, value11, value2 ...
  4. }

或者命名返回值

  1. func functionName(input1, input11 type1, input2 type2 ...) (output1 type1, output11 type11, output2 type2 ...){
  2. //函数体
  3. output1 = ...
  4. output11 = ...
  5. output2 = ...
  6. ...
  7. return
  8. }

6. 导出名

前面我们已经使用了import导入功能,比如improt "fmt",该行代码可以让我们在本包中使用其他包里的函数。

那么我们如何让其他包能够使用到本包的方法或变量呢?答案是:将方法或变量导出

在Go语言中,如果一个名字以大写字母开头,那么它就是已导出的,这意味着别的包可以使用它。(相当于Java中的public的作用)

比如我们常用的打印函数fmt.Println(...),可以看到Println()的首字母是大写的,所以我们能够导入fmt包后使用该方法。

7. 流程控制语句

7.1. if语句

if语句是条件判断语句,用来判断是否满足某种条件,如果满足,则执行某段代码;如果不满足,则不执行。

  1. if ... {
  2. //代码
  3. } else if ... {
  4. //代码
  5. } else {
  6. //代码
  7. }

注意格式:条件判断语句不需要使用小括号()

下面是几个例子:

  1. if a > 0 {//如果满足a>0,则打印Hello, World
  2. fmt.Println("Hello, World")
  3. }
  1. if a > 0 {//如果满足a>0,则打印 Hello, World
  2. fmt.Println("Hello, World!")
  3. } else {//否则(即不满足a>0),则打印 你好,世界!
  4. fmt.Println("你好,世界!")
  5. }
  1. if a > 5 {//如果满足a>5,则打印 Hello, World
  2. fmt.Println("Hello, World!")
  3. } else if a <= 5 && a > 0 {//如果满足0<a<=5,则打印 好好学习,天天向上
  4. fmt.Println("好好学习,天天向上")
  5. } else {//否则(即上面的条件都不满足),则打印 你好,世界!
  6. fmt.Println("你好,世界!")
  7. }

Go语言的if语句有一个特性:可以在条件表达式前执行一个简单的语句。下面是一个例子:

  1. package main
  2. import "fmt"
  3. func sum(x, y int) int {
  4. return x + y
  5. }
  6. func main () {
  7. if i := sum(1, 2); i > 0 {
  8. fmt.Println("Hello, World!")//作用域内,能打印i
  9. }
  10. //fmt.Println(i)//作用域外,不能打印i
  11. }

在if语句中,使用sum(x, y int)函数计算出i的值,再进行判断。注意:变量i的作用域只在if语句中有效。

7.2. for语句

for语句是Go语言中的循环控制语句。它有几种形式:

(一)基本形式:

  1. for 初始化语句; 条件表达式; 后置语句 {
  2. //循环体代码
  3. }
  • 初始化语句:在第一次循环前之前,且只执行这一次
  • 条件表达式:每次循环都会计算该表达式,如果满足(值为true)则继续循环;如果不满足(值为false),则跳出循环
  • 后置语句:每次循环执行完都会执行该语句

下面是一个例子,循环打印5次"Hello,World!"

  1. for i := 0; i < 5; i++ {
  2. fmt.Println("Hello, World!", i)
  3. }

注意该例的初始化语句i := 0是一个短变量声明,变量i只在该for循环中生效。

(二)省略形式:

for循环中的初始化语句和后置语句是可以省略的。

  1. i := 0
  2. for ; i < 5; i++ {
  3. fmt.Println("Hello, World!", i)
  4. }
  1. i := 0
  2. for ; i < 5; {
  3. fmt.Println("Hello, World!", i)
  4. i++
  5. }

从某种意义上来讲,上面两个例子并没有省略初始化语句或后置语句,只是改变了位置。

(三)while形式

诸如C、Java等语言中都有while循环,但是Go语言中没有while循环,但是我们可以使用for循环来实现“while循环”。

其实(二)省略形式中的第二个for循环例子就已经可以看做是while循环了。我们再稍做改进:

  1. i := 0
  2. for i < 5 {//去掉两个分号,只写条件表达式
  3. fmt.Println("Hello, World!", i)
  4. i++
  5. }

(四)无限循环形式

  1. //打印无限多个Hello, World!
  2. for {
  3. fmt.Println("Hello, World!")
  4. }

7.3. break和continue

上面提到的循环语句只有当条件表达式的值为false时,才会停止循环。但实际开发中,我们可能在条件表达式的值为true的情况下,需要退出循环。这种时候,就需要使用breakcontinue语句。

break语句用来跳出当前循环,continue语句用来跳过本次循环。

下面是两个实例(改进上面循环打印5次"Hello,World!"的例子):

实例1:增加需求,当打印完第2遍Hello,World!时,停止打印

  1. for i := 0; i < 5; i++ {
  2. if i == 2 {
  3. break
  4. }
  5. fmt.Println("Hello, World!", i)
  6. }

实例2:增加需求,不打印第3遍Hello,World!

  1. for i := 0; i < 5; i++ {
  2. if i == 2 {
  3. continue
  4. }
  5. fmt.Println("Hello, World!", i)
  6. }

7.4. switch语句

我们可以使用if...else if...else if...进行一连串的条件判断,但是这样过于繁杂。switch语句就是用来简化这个问题的。

  1. switch 变量 {
  2. case 选项1 :
  3. //操作1代码
  4. case 选项2 :
  5. //操作2代码
  6. case 选项3 :
  7. //操作3代码
  8. case 选项n:
  9. //操作n代码
  10. default :
  11. //默认操作
  12. }

switch语句中有许多case和一个default,只有当变量和case的选项相匹配时,才会执行对应的操作代码。如果没有case的选项可以匹配,则默认执行default的代码。

下面是一个例子:

  1. package main
  2. import "fmt"
  3. func sum(x, y int) int {
  4. return x + y
  5. }
  6. func main () {
  7. result := sum(3, 2)
  8. switch result {
  9. case 1 :
  10. fmt.Println("结果为1")
  11. case 2, 3, 4: //多种情况聚合在一起
  12. fmt.Println("结果为2或3或4")
  13. case sum(1, 4): //支持表达式
  14. fmt.Println("结果为5")
  15. default:
  16. fmt.Println("其他结果")
  17. }
  18. }

从上面的例子可以看出,Go语言中switch的case支持常量(不必为整数)、表达式、多个值聚合。注意:不论是常量、表达式,还是多个值聚合,都要保证常量、表达式的值、多个值的类型和switch的变量相同。

switch语句的匹配顺序是自上到下。Go语言自动为每个case提供了break语句,所以在众多选项中只能执行1个casedefault,然后结束,剩余的不再执行。

但是可以使用fallthrough强制执行剩余的case:

  1. result := sum(1, 1)
  2. switch result {
  3. case 1 :
  4. fmt.Println("结果为1")
  5. fallthrough
  6. case 2, 3, 4:
  7. fmt.Println("结果为2或3或4")
  8. fallthrough
  9. case sum(1, 4):
  10. fmt.Println("结果为5")
  11. fallthrough
  12. default:
  13. fmt.Println("其他结果")
  14. }

还是上面的那个例子,但是在每个case中使用fallthrough,现在的打印结果为:

  1. 结果为234
  2. 结果为5
  3. 其他结果

如有错误,还请指正。

文章首发于公众号『行人观学』

Go语言基础语法总结的更多相关文章

  1. C语言基础语法

    #include <stdio.h> int main() { int age; printf("input your age"); scanf("%d&qu ...

  2. Smali语言基础语法

    1.Smali语言基础语法-数据类型与描述符 smali中有两类数据类型:基本类型和引用类型.引用类型是指数组和对象,其它都是基础类型. 基本类型以及每种类型的描述符: Java类型 类型描述符 说明 ...

  3. 黑马程序员——OC语言基础语法 面向对象的思想

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结)(一)基础语法 1)关键字 @interface.@implementati ...

  4. 黑马程序员——C语言基础语法 关键字 标识符 注释 数据及数据类型

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (一下内容是对黑马苹果入学视频的个人知识点总结) (一)C语言简单介绍 (1)C语言程序是由函数组成的任何C语言程序都是由一 ...

  5. php语言基础语法与编程工具推荐

    php脚本语言,需要在服务器端执行,用浏览器返回HTML结果.在PHP中所有的语法都是如此,用户端是无法修改的,只有浏览权限. 一.php基础语法之输出方法 1.PHP中所有的脚本,可以放在文件中的任 ...

  6. C语言基础语法之指向函数的指针

    指针是C语言的精髓,对于初学者来讲,指针是C语言语法学习中比较难的知识点,而这里面指向函数的指针更是不太容易理解. 下面给大家讲下怎样学习理解C语言中指向函数的指针及编程方法和使用例子. 注意:这是一 ...

  7. Python语言基础-语法特点、保留字与标识符、变量、基本数据类型、运算符、基本输入输出、Python2.X与Python3.X区别

    Python语言基础 1.Python语法特点 注释: 单行注释:# #注释单行注释分为两种情况,例:第一种#用于计算bim数值bim=weight/(height*height)第二种:bim=we ...

  8. NDK以及C语言基础语法(一)

    一.什么是NDK? Native Development Kit (本地开发工具包): NDK中提供了一系列的工具,帮助我们快速开发C/C++的动态库,并能自动将so文件和java文件一起打包成apk ...

  9. Go语言--基础语法笔记

    ### 换了工作,好久没有添加新文章了,本来是想更新到github上的,想想还是在博客里放着,感觉以前的文章都没有很仔细,都只是问题处理的记录, 以后想新加一些整理的笔记也好 ### 主要内容 2.1 ...

  10. GO_03:GO语言基础语法

    1. Go项目的目录结构 一般的,一个Go项目在GOPATH下,会有如下三个目录: project   --- bin   --- pkg   --- src 其中,bin 存放编译后的可执行文件:p ...

随机推荐

  1. 用一杯茶时间搭建Gitea服务器

     一.简单介绍 Gitea搭建局域网内的基于git的代码托管服务器,可以实现的功能包括:组织管理.团队管理.组织仓库设定.团队仓库分配.组织及团队权限分配管理.仓库添加PC协作者.仓库添加组织团队.分 ...

  2. 【转载】张一鸣:为什么 BAT 挖不走我们的人才?

    很多企业失败的时候,总说是政策的变化.市场的变化.消费者需求的变化.技术发展的变化等等,导致了失败,其实这都是瞎说,归根结底还是人的原因,都是因为你招的人不行.可见,人才对于一个企业的重要性. 互联网 ...

  3. 《算法笔记》9.4小节 问题 B: 二叉搜索树

    这道题也当做二叉搜索树的建树模板. 这道题其实直接把这颗树建出来后,比较前序序列和中序序列即可,这里我用的数组实现,更好写和查错qwq. code: #include <bits/stdc++. ...

  4. 简单案例:form表单应用向后端发数据

    效果如下图: 先新建一Django项目. 最后在terminal执行python manage.py runserver 8090 运行djago程序 浏览器输入http://127.0.0.1:80 ...

  5. linux根据进程查端口,根据端口查进程

    [root@test_environment src]# netstat -tnllup   能显示对应端口和进程 Active Internet connections (only servers) ...

  6. .net core Web API参数绑定规则

    参数推理绑定 先从一个问题说起,微信小程序按照WebAPI定义的参数传递,Get请求服务器端可以正常接收到参数,但是Post请求取不到. Web API代码(.netcore 3.1)如下: [Htt ...

  7. 每日一题 - 剑指 Offer 39. 数组中出现次数超过一半的数字

    题目信息 时间: 2019-06-29 题目链接:Leetcode tag: 数组 哈希表 难易程度:简单 题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 假设数组是非空的 ...

  8. 3.Unity3d物体操作常用按键

    新建一个cube物体.在unity3d界面左上角可以看到红色下划线的五个图标(下面用图标1到5数字表示),分别对应不同功能,这些功能操作物体很常用.下面用cube物体的操作来演示这几个功能. 1.按Q ...

  9. URL编码与二次encodeURI

    转自:http://foryougeljh.iteye.com/blog/1456706 一般来说,URL只能使用英文字母.阿拉伯数字和某些标点符号,不能使用其他文字和符号.比如,世界上有英文字母的网 ...

  10. 静态方法中注入bean

    @Componentpublic class ScriptExecuteContent { @Autowired private static SignRepository signRepositor ...