1. 意识HelloWorld

在后面的《Go的装置和应用》这篇文章中曾经写过HelloWorld.go了,当初就来逐行认识一下它。

package mainimport "fmt"func main() {    fmt.Println("Hello, World!")}

第1行:咱们的Go程序是由——package形成的,包的申明模式为:package <包名>。该行的意思是:以后HelloWorld.go文件属于main包。

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

import "fmt"import "math"

或者应用分组模式同时导入多个包

import (    "fmt"    "math/rand")

显然第二种应用括号,以分组的模式导入更加不便。

第3行:咱们应用func关键字来申明一个函数,在这个例子中,咱们申明的是main函数。如果你有过其余语言的编程教训,必定相熟main函数的作用:程序的入口。

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

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

2. 变量

2.1. 命名标准

Go语言要求标识符以一个字母或下划线结尾,前面能够跟任意数量的字母、数字、下划线。不能应用关键字作为标识符

辨别大小写,变量num和变量Num是两个变量。

2.2. 申明

Go语言的变量申明形式和其余语言(如C、Java、Python)不太一样。

比方,咱们申明一个为int类型的变量a:

var a int

能够看出,Go语言申明变量的形式为:

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

咱们还能够同时申明多个类型雷同的变量:

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

应用分组同时申明多个类型不同的变量:

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

上面是一个具体的例子:

package mainimport "fmt"var i bool//类型在后func main() {    var a, b, c int//多个    fmt.Println(i, a, b, c)}

2.3. 初始化

当咱们申明变量时,能够对其进行初始化。当有初始值时,咱们能够省略变量的类型,变量会依据对应的初始值获取正确的类型。见下例:

package mainimport "fmt"var a int = 1var b, c bool = true, falsefunc main() {    var i, j, k = 2, false, "行小观"    //省略变量类型    fmt.Println(a, b, c, i, j, k)    k = "行小观2号" //赋值操作    fmt.Println(k)}

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

这些零值为:

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

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

package mainimport "fmt"var a intvar b, c boolfunc main() {    var i int    var j bool    var k string    fmt.Println(a, b, c, i, j, k)}

则打印后果为:0 false false 0 false (变量k因为是空字符串,所以打印进去了然而看不到)

2.4. 短变量申明

后面介绍了当咱们申明变量时有以下几种形式:

var i int    //申明一个int变量var i, j, k int    //同时申明多个int变量var i int = 1    //申明一个int变量并初始化var i, j, k int = 1, 2, 3    //同时申明多个int变量并别离初始化var i = 1    //省略类型,申明一个int变量并初始化var i, j, k = 1, 2, 3    //省略类型,同时申明多个int变量并别离初始化

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

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

当咱们应用:=申明变量时,不必写var也不必写类型,然而这种形式只能在函数外部应用,不能在函数内部应用。当在函数内部申明变量时,只能应用var

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

此外,咱们申明的变量必须要应用,如果申明了变量,然而没应用,会在编译时报错。比方:

package mainimport "fmt"func main() {    var i bool    var j int //申明了,但没应用,会报错    fmt.Println(i)}

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

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

留神:不同类型的变量之间不能间接进行赋值或其余运算(比方加减乘除)

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

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

[报错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。留神是转换的是变量的值,变量自身的类型不变。

package mainimport "fmt"var (    a int = 1    b int8 = 2    c uint    d int64)func main() {    c = uint(b) //将变量b的值2的类型从int8转换为uint    d = int64(a) + int64(b)    fmt.Printf("c(%T):%v = b(%T):%v\n", c, c, b, b)    fmt.Printf("a(%T):%v + b(%T):%v = d(%T):%v\n", a, a, b, b, d, d)}

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

4. 常量

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

常量能够定义为数值、字符串、布尔类型

常量的申明形式和变量差不多,区别在于常量须要用const关键字润饰,不能应用:=进行申明。

package mainimport "fmt"const num int = 555var a int = 1func main() {    const world = "世界"    const truth = true    fmt.Println("Hello,", world)    fmt.Println("num = ", num)    fmt.Println("a = ", a)    fmt.Println("对吗?", truth)}

5. 初识函数

如果你之前学习过C或者Java等语言,必定曾经对函数(办法)有了肯定的意识。

简略地来说,函数是对能实现某个性能的局部代码的形象。当当前再须要该性能,咱们只须要调用其对用的函数即可,不用再反复编写代码。

5.1. 函数的申明

咱们在后面的内容曾经应用到了函数,即main()。咱们应用func关键字申明函数。

func func_name() {    }

5.2. 函数的参数

Go语言中,函数能够有0个或多个参数。

package mainimport "fmt"func printName(name string, age int) {    fmt.Println("我叫", name, ", 往年", age, "岁了")}func sayHello() {    fmt.Println("行小观说:“你好”")}func main() {    printName("行小观", 1)    sayHello()}

如果你有多个参数的类型雷同,你能够进行简写,只须要在这几个雷同的参数最初写一遍类型即可。

func foo(x int, y int, z int)能够简写为:func foo(x, y, x int)

5.3. 函数的类型和返回值

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

package mainimport "fmt"func add(x int, y int) int {    return x + y}func main() {    fmt.Println(add(1, 2))}

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

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

函数能够有0个或多个返回值

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

package mainimport "fmt"func sumAndDiff(x, y int) (int, int) { //两个返回值类型    sum := x + y    diff := x - y    return sum, diff //两个返回值}func main() {    a, b := sumAndDiff(5, 1)    fmt.Println(a, b)}

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

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

顾名思义,咱们通过给返回值进行命名,应用空return语句,这样会间接返回已命名的返回值。如上例的sumAndDiff函数能够写为:

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

上面总结一下函数的应用:

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

或者命名返回值

func functionName(input1, input11 type1, input2 type2 ...) (output1 type1, output11 type11, output2 type2 ...){        //函数体    output1 = ...    output11 = ...    output2 =  ...    ...    return}

6. 导出名

后面咱们曾经应用了import导入性能,比方improt "fmt",该行代码能够让咱们在本包中应用其余包里的函数。

那么咱们如何让其余包可能应用到本包的办法或变量呢?答案是:将办法或变量导出

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

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

7. 流程管制语句

7.1. if语句

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

if ... {    //代码} else if ... {    //代码} else {    //代码}

留神格局:条件判断语句不须要应用小括号()

上面是几个例子:

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

Go语言的if语句有一个个性:能够在条件表达式前执行一个简略的语句。上面是一个例子:

package mainimport "fmt"func sum(x, y int) int {    return x + y}func main ()  {    if i := sum(1, 2); i > 0 {        fmt.Println("Hello, World!")//作用域内,能打印i    }    //fmt.Println(i)//作用域外,不能打印i}

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

7.2. for语句

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

(一)根本模式:

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

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

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

留神该例的初始化语句i := 0是一个短变量申明,变量i只在该for循环中失效。

(二)省略模式:

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

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

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

(三)while模式

诸如C、Java等语言中都有while循环,然而Go语言中没有while循环,然而咱们能够应用for循环来实现“while循环”。

其实(二)省略模式中的第二个for循环例子就曾经能够看做是while循环了。咱们再稍做改良:

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

(四)有限循环模式

//打印有限多个Hello, World!for  {    fmt.Println("Hello, World!")}

7.3. break和continue

下面提到的循环语句只有当条件表达式的值为false时,才会进行循环。但理论开发中,咱们可能在条件表达式的值为true的状况下,须要退出循环。这种时候,就须要应用breakcontinue语句。

break语句用来跳出以后循环,continue语句用来跳过本次循环。

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

实例1:减少需要,当打印完第2遍Hello,World!时,进行打印

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

实例2:减少需要,不打印第3遍Hello,World!

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

7.4. switch语句

咱们能够应用if...else if...else if...进行一连串的条件判断,然而这样过于繁冗。switch语句就是用来简化这个问题的。

switch 变量 {    case 选项1 :        //操作1代码    case 选项2 :        //操作2代码    case 选项3 :        //操作3代码    case 选项n:        //操作n代码    default :        //默认操作}

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

上面是一个例子:

package mainimport "fmt"func sum(x, y int) int {    return x + y}func main ()  {    result := sum(3, 2)    switch result {    case 1 :        fmt.Println("后果为1")    case 2, 3, 4:    //多种状况聚合在一起        fmt.Println("后果为2或3或4")    case sum(1, 4):    //反对表达式        fmt.Println("后果为5")    default:        fmt.Println("其余后果")    }}

从下面的例子能够看出,Go语言中switch的case反对常量(不用为整数)、表达式、多个值聚合。留神:不论是常量、表达式,还是多个值聚合,都要保障常量、表达式的值、多个值的类型和switch的变量雷同。

switch语句的匹配程序是自上到下。Go语言主动为每个case提供了break语句,所以在泛滥选项中只能执行1个casedefault,而后完结,残余的不再执行。

然而能够应用fallthrough强制执行残余的case:

result := sum(1, 1)switch result {    case 1 :    fmt.Println("后果为1")    fallthrough    case 2, 3, 4:    fmt.Println("后果为2或3或4")    fallthrough    case sum(1, 4):    fmt.Println("后果为5")    fallthrough    default:    fmt.Println("其余后果")}

还是下面的那个例子,然而在每个case中应用fallthrough,当初的打印后果为:

后果为2或3或4后果为5其余后果
如有谬误,还请斧正。

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