Go 语言入门指南:基础语法和常用特性解析 (上)| 青训营

115 阅读12分钟

一、HelloWorld

“HelloWorld”是程序员对这个世界的第一次呐喊,所以学习这门语言之初,我们就从hello.go开始吧!

在GO语言里,命名为main的包具有特殊的含义,Go语言的编译程序会试图把这种名字的包编译为二进制可执行文件,所有用Go语言编译的可执行程序都必须有一个名叫main的包,一个可执行程序有且仅有一个main包。 当编译器发现某个包的名字为main时,它一定也会发现名为main()的函数,否则不会创建可执行文件。main()函数是程序的入口,所以,如果没有这个函数,程序就没有办法开始执行,程序编译时,会使用声明main包的代码所在的目录名作为二进制可执行文件的文件名。

二、基础语法

1.变量

所谓变量,就是可以变化的量。使用var关键字定义函数,函数可以有参数和返回值。函数可以是包级别的,也可以是局部的。例如:func add(a, b int) int { return a + b }

这是一个简单的Go语言程序。下面是对程序进行逐行解释。(解释的序号与代码前的行数一致,方便大家查看)

1.package main 表示这个文件属于 main 包,main是一个特殊的包名,它标识这个文件是一个可执行的程序,而不是一个库文件。

3.使用 import 关键字导入了两个包,fmtmathfmt 包提供了基本的格式化和输入输出功能,math 包提供了数学函数。

7.func main() 是主函数的定义,是程序执行的入口。

8.var a = "initial" 声明并初始化了一个变量 a,其类型会从初始值进行推断。

9.var b, c int = 1, 2 声明并初始化了两个整型变量 bc

10.var d = true 声明并初始化了一个布尔型变量 d

11.var e float64 声明了一个浮点型变量 e,未给其赋初值。默认为该类型的零值。

13.f := float32(e) 声明并初始化了一个浮点型变量 f,其值从 e 进行类型转换。

14.g := a + "foo" 声明并初始化了一个字符串变量 g,其值由 a 和字面值 "foo" 拼接而成。

15.fmt.Println 函数用来将结果输出到标准输出,这里输出了上述变量的值。

16.const 关键字用于声明常量,s 是一个字符串常量,h 是一个整型常量,i 是一个浮点型常量。

18、19、20. 再次使用 fmt.Println 输出常量 s、 h、 i、 math.Sin(h)math.Sin(i) 的值。

总的来说,这个程序演示了Go语言中的变量声明、类型推断、常量和基本的输出功能。

2.if else

这是一个简单的Go语言程序,演示了条件语句的使用。下面是对程序进行逐行的解释: if 7%2 == 0 是一个条件语句,判断 7 是否能被 2 整除。如果条件为真,则执行 {} 内的代码块;否则执行 else 后的代码块。 if 8%4 == 0 同样是一个条件语句,判断 8 是否能被 4 整除。条件为真,则执行 {} 内的代码块。 if num := 9; num < 0 是一个带有初始化语句的条件语句。首先,定义了一个变量 num 并赋值为 9。然后判断 num 是否小于 0,如果条件为真,则执行 {} 内的代码块。如果条件为假,则判断 num 是否小于 10,如果条件为真,则执行下一个代码块;如果条件都不满足,则执行 else 后的代码块。

3.循环

这是一个使用循环的Go语言程序。下面是对程序进行逐行的解释:

i := 1  
for {  
    fmt.Println("loop")  
    break  
}

这段代码使用了一个无限循环,并在循环体内打印出字符串 "loop"。然后,通过 break 关键字退出循环。

for j := 7; j < 9; j++ {  
    fmt.Println(j)  
}

这段代码使用了一个简单的 for 循环, j 的初始值为 7,每次循环后 j 的值加 1。循环的条件是j小于 9。在循环体内,打印出 j 的值。

for n := 0; n < 5; n++ {  
    if n%2 == 0 {  
        continue  
    }  
    fmt.Println(n)  
}

这段代码使用了一个 for 循环,n 的初始值为 0,每次循环后 n 的值加 1。循环的条件是 n 小于 5。在循环体内,判断n是否为偶数,如果是偶数,则使用 continue 关键字跳过本次循环。如果是奇数,则打印出n的值。

for i <= 3 {  
    fmt.Println(i)  
    i = i + 1  
}

这段代码使用了一个 for 循环,循环的条件是 i 小于等于 3。在循环体内,打印出 i 的值,然后将 i 的值加 1。循环会一直执行,直到 i 大于 3

总的来说,这个程序演示了Go语言中不同类型的循环语句的使用,包括无限循环、带有计数器的循环、跳过循环和基于条件的循环。

4.switch

这是一个使用 switch 语句的Go语言程序。下面是对程序进行逐行的解释:

a := 1  
switch a {  
case 1:  
    fmt.Println("one")  
case 2:  
    fmt.Println("two")  
case 3:  
    fmt.Println("three")  
case 4, 5:  
    fmt.Println("four or five")  
default:  
    fmt.Println("other")  
}

这段代码使用了 switch 语句根据变量 a 的值执行不同的代码分支。当 a 的值为 1 时,输出 "one";当 a 的值为 2 时,输出 "two";当 a 的值为 3 时,输出 "three";当 a 的值为 45 时,输出 "four or five";其他情况下,输出 "other"。

t := time.Now()  
switch {  
case t.Hour() < 12:  
    fmt.Println("It's before noon")  
default:  
    fmt.Println("It's after noon")  
}

这段代码使用了一个不带条件的 switch 语句来根据当前时间判断是上午还是下午。如果当前时间的小时数小于 12,输出 "It's before noon";否则,输出 "It's after noon"

总的来说,这个程序演示了不同情况下使用 switch 语句的能力,它可以根据变量的值或条件来决定执行的代码分支。

5.数组

这是一个关于数组的Go语言程序。下面是对程序进行逐行的解释:

var a [5]int  
a[4] = 100  
fmt.Println(a[4], len(a))

这段代码定义了一个长度为 5 的整数数组 a。然后,将数组中索引为 4 的元素赋值为 100。接着,通过打印 a[4]len(a),输出数组中索引为 4 的元素的值(即 100)和数组的长度(即 5)。

b := [5]int{1, 2, 3, 4, 5}  
fmt.Println(b)

这段代码定义了一个长度为 5 的整数数组 b,并初始化数组的值为 {1, 2, 3, 4, 5}。然后,通过打印 b,输出整个数组的值。

var twoD [2][3]int  
for i := 0; i < 2; i++ {  
    for j := 0; j < 3; j++ {  
        twoD[i][j] = i + j  
    }  
}  
fmt.Println("2d:", twoD)

这段代码定义了一个二维整数数组 twoD,大小为 2x3,即两行三列。接着,通过两个嵌套的 for 循环,遍历数组中的每一个元素,并将两个索引的和赋值给数组的对应元素。最后,通过打印 twoD,输出整个二维数组的值。

总的来说,这个程序演示了在Go语言中声明、初始化和访问数组的方法,以及如何操作二维数组。

6.切片

这是一个关于切片的Go语言程序。下面是对程序进行逐行的解释:

s := make([]string, 3)  
s[0] = "a"  
s[1] = "b"  
s[2] = "c"  
fmt.Println("get:", s[2])  
fmt.Println("len:", len(s))

这段代码使用 make 函数创建了一个长度为 3 的切片 s。然后,分别给切片的索引为 0、12 的位置赋值为 "a"、"b""c"。接着,通过打印 s[2],输出切片中索引为 2 的元素的值(即 "c")。再通过打印 len(s),输出切片的长度(即 3)。

s = append(s, "d")  
s = append(s, "e", "f")  
fmt.Println(s)

这段代码使用 append 函数向切片 s 中追加了元素。首先,追加了一个元素 "d";然后,追加了两个元素 "e" "f"。最后,通过打印 s,输出追加后的切片。

c := make([]string, len(s))  
copy(c, s)  
fmt.Println(c)

这段代码使用 make 函数创建了一个与切片 s 长度相同的切片 c。然后,使用 copy 函数将切片 s 的内容复制到切片 c 中。最后,通过打印 c,输出复制后的切片。

fmt.Println(s[2:5])  
fmt.Println(s[:5])  
fmt.Println(s[2:])

这段代码演示了切片的切割操作。s[2:5] 表示从切片 s 中索引为 2(包含)到索引为 5(不包含)的子切片;s[:5] 表示从切片 s 的开头开始到索引为 5(不包含)的子切片;s[2:] 表示从切片 s 索引为 2(包含)到末尾的子切片。通过打印这些子切片,输出相应的结果。

good := []string{"g", "o", "o", "d"}  
fmt.Println(good)

这段代码创建了一个字符串切片 good,并初始化了切片的值为 {"g", "o", "o", "d"}。然后,通过打印 good,输出整个切片的值。

总的来说,这个程序演示了在Go语言中使用切片的各种操作,包括创建切片、获取切片元素、追加元素、复制切片以及对切片进行切割。

7.map

这是一个关于映射(map)的Go语言程序。下面是对程序进行逐行的解释:

m := make(map[string]int)  
m["one"] = 1  
m["two"] = 2  
fmt.Println(m)  
fmt.Println(len(m))  
fmt.Println(m["one"])  
fmt.Println(m["unknown"])

这段代码使用 make 函数创建了一个新的映射 m,键的类型为 string,值的类型为 int。然后,给映射 m 分别赋值为 {"one":1, "two":2}。通过打印 m,输出整个映射的键值对。接着,通过打印 len(m),输出映射的键值对数量。然后,通过打印 m["one"],输出映射中键为 "one" 对应的值。最后,通过打印 m["unknown"],输出映射中不存在的键对应的值(值的类型的零值)。

r, ok := m["unknown"]  
fmt.Println(r, ok)

这段代码演示了通过访问映射的方式来获取值,并检查是否存在对应的键。首先,通过 m["unknown"] 获取键为 "unknown" 的值,然后将该值赋给变量 r。同时,通过 ok 变量接收一个布尔值,表示是否成功获取到键的值。通过打印 rok,即可输出相应的结果。

delete(m, "one")

这段代码使用 delete 函数从映射 m 中删除键为 "one" 的键值对。

m2 := map[string]int{"one": 1, "two": 2}  
var m3 = map[string]int{"one": 1, "two": 2}  
fmt.Println(m2, m3)

这段代码演示了不同的创建映射的方式。m2 是使用字面值初始化的映射,键为 "one""two",相应的值为 12m3 是使用显式类型声明并使用字面值初始化的映射。通过打印 m2 m3,输出所有的键值对。

总的来说,这个程序演示了在Go语言中使用映射的各种操作,包括创建映射、给键赋值、获取映射的长度、通过键获取对应的值、检查映射中是否存在某个键、删除键值对以及不同方式的映射创建。

8.range

这是一个关于使用循环遍历切片和映射的Go语言程序。下面是对程序进行逐行的解释:

nums := []int{2, 3, 4}  
sum := 0  
for i, num := range nums {  
  sum += num  
  if num == 2 {  
    fmt.Println("index:", i, "num:", num)  
  }  
}  
fmt.Println(sum)

这段代码创建了一个整型切片 nums,并初始化了切片的值为 {2, 3, 4}。然后,定义一个整型变量 sum 并初始化为0。通过 range 关键字遍历切片 nums,同时获取元素的索引i和对应的值 num。在循环中,将当前值 num 累加到变量 sum 中。如果 num 的值等于2,就通过打印语句输出索引和值。最后,通过打印 sum,输出切片中所有元素的和。

m := map[string]string{"a": "A", "b": "B"}  
for k, v := range m {  
  fmt.Println(k, v)  
}

这段代码创建了一个字符串映射 m,并初始化了映射的键值对为 {"a": "A", "b": "B"}。通过 range 关键字遍历映射 m,同时获取键 k 和对应的值 v,然后通过打印语句输出键和值。

for k := range m {  
  fmt.Println("key", k)  
}

这段代码通过 range 关键字遍历映射 m 中的键,并将键赋给变量 k。然后通过打印语句输出键。

总的来说,这个程序演示了如何使用循环遍历切片和映射,并在遍历过程中对元素进行操作,例如累加求和、打印特定值和打印键值对。

9.函数

这是一个使用函数的Go语言程序。下面是对程序进行逐行的解释:

func add(a int, b int) int {  
  return a + b  
}

这段代码定义了一个名为 add 的函数,接受两个整型参数 ab,并返回它们的和。

func add2(a, b int) int {  
  return a + b  
}

这段代码定义了一个名为 add2 的函数,与上面的 add 函数相比,省略了参数的类型声明,因为它们都是同一类型。

func exists(m map[string]string, k string) (v string, ok bool) {  
  v, ok = m[k]  
  return v, ok  
}

这段代码定义了一个名为 exists 的函数,接受一个字符串映射 m 和一个字符串键 k,并返回映射中对应键的值和一个布尔值,表示是否存在该键。在函数内部,通过 m[k] 获取键对应的值,并将值和一个布尔值赋给变量 vok,然后将它们作为结果返回。

func main() {  
  res := add(1, 2)  
  fmt.Println(res)  
  
  v, ok := exists(map[string]string{"a": "A"}, "a")  
  fmt.Println(v, ok)  
}

这段代码在 main 函数中调用了上面定义的 add 函数和 exists 函数。将调用 add(1, 2) 的结果赋给变量 res,然后通过打印语句输出结果。接着,调用 exists 函数,并将返回的值赋给变量 vok,然后通过打印语句输出这两个变量的值。

总的来说,这个程序演示了如何定义和使用函数,包括函数的参数和返回值的声明,以及函数的调用和结果的处理。

由于内容太长,打算分两部分发布,期待下一次的分享......