GO语言基础语法 | 青训营笔记

56 阅读11分钟

什么是GO语言?

GO语言是一种开源的编程语言,由Google的Robert Griesemer, Rob Pike和Ken Thompson于2009年设计和发布。GO语言的目标是提供一种简洁、高效、可靠和跨平台的编程工具,适用于各种应用场景,如系统编程、网络编程、并发编程和云计算等。

GO语言的特点

GO语言具有以下几个特点:

  • 语法简单:GO语言的语法类似于C语言,但去除了一些复杂和冗余的特性,如指针运算、类型转换、继承和泛型等。GO语言也引入了一些新的特性,如切片(slice)、映射(map)、接口(interface)和goroutine等,使得编程更加灵活和高效。
  • 编译速度快:GO语言采用了模块化的编译方式,每个文件都是一个编译单元,只需要编译自身和依赖的包,而不需要链接整个程序。这样可以大大提高编译速度和可维护性。
  • 并发支持:GO语言原生支持并发编程,通过goroutine和通道(channel)来实现轻量级的线程和数据交互。goroutine是一种用户态的协程,可以在一个操作系统线程上运行多个goroutine,实现高并发和低开销。通道是一种同步的消息传递机制,可以在不同的goroutine之间安全地传递数据。
  • 内存管理:GO语言使用了自动垃圾回收(GC)机制来管理内存,无需手动分配和释放内存。GO语言的GC采用了三色标记清除算法,并且通过分代回收、写屏障、并发标记等技术来降低GC的停顿时间和影响。
  • 标准库丰富:GO语言提供了一套完善的标准库,涵盖了常用的数据结构、算法、网络、数据库、测试、加密等功能。标准库的接口设计遵循了统一和简洁的原则,易于学习和使用。

GO语言的安装和使用

要使用GO语言,首先需要安装GO语言的开发环境。可以从官网(golang.org/)下载对应操作系统的安装包,并按照说明进行安装。安装完成后,需要设置环境变量GOROOT(指向GO语言安装目录)和GOPATH(指向工作目录),以便于编译器和工具找到相关文件。

要编写GO语言程序,可以使用任何文本编辑器或集成开发环境(IDE)。推荐使用Visual Studio Code(code.visualstudio.com/)作为编辑器,并安装GO语言扩展(marketplace.visualstudio.com/items?itemN…),以获得代码提示、格式化等等

GO语言的基本语法

GO语言的基本语法包括以下几个方面:

  • 标识符:标识符是用来命名变量、常量、函数、类型等程序实体的名称。标识符由字母、数字和下划线组成,但不能以数字开头,也不能是关键字或预定义的标识符。标识符区分大小写,建议使用驼峰式命名法(如firstName)。
  • 关键字:关键字是有特殊含义的单词,不能用作标识符。GO语言有25个关键字,如下:

| break | default | func | interface | select | | case | defer | go | map | struct | | chan | else | goto | package | switch | | const | fallthrough | if | range | type | | continue | for | import | return | var |

  • 预定义标识符:预定义标识符是已经定义好的标识符,可以直接使用,但也可以重新定义。GO语言有37个预定义标识符,如下:

| append | bool | byte | cap | close | complex | complex64 | complex128 | | uint16 | uint32 | uint64 | uintptr | | copy | false | float32| float64| imag | int | int8 | int16 | | len | make | new | nil | panic | print | println | | real | recover | string | true | | int32 | int64 | | uint | uint8 |

  • 注释:注释是用来解释代码的文字,不会被编译器执行。GO语言支持两种形式的注释:单行注释和多行注释。单行注释以双斜线(//)开头,多行注释以斜线星号(/ )开头,以星号斜线( /)结尾。例如:
// 这是一个单行注释
/* 这是一个
多行注释 */
  • 变量:变量是用来存储数据的容器,每个变量都有一个类型,表示可以存储什么样的数据。GO语言支持静态类型和动态类型两种方式来声明变量。静态类型的声明方式是在变量名后面指定类型,如:
var x int // 声明一个名为x的整型变量

动态类型的声明方式是使用短变量声明符(:=),让编译器自动推断类型,如:

x := 10 // 声明一个名为x的变量,并赋值为10

注意:短变量声明符只能用在函数内部,不能用在全局变量的声明。

  • 常量:常量是指在程序运行过程中不会改变的值。常量的声明方式和变量类似,只是使用const关键字代替var关键字。常量可以是基本类型(如整数、浮点数、布尔值、字符串等)或者复合类型(如数组、结构体、切片等)。例如:
const pi = 3.14 // 声明一个名为pi的常量,并赋值为3.14
const (
  a = 1 // 声明一个名为a的常量,并赋值为1
  b = 2 // 声明一个名为b的常量,并赋值为2
)
  • 数据类型:数据类型是指可以存储在变量或常量中的数据的种类。GO语言支持以下几种数据类型:

    • 基本类型:基本类型包
      • 基本类型:基本类型包括数值类型(整数、浮点数、复数)、布尔类型(true或false)和字符串类型(一系列的字符)。例如:
var i int = 10 // 声明一个名为i的整型变量,并赋值为10
var f float64 = 3.14 // 声明一个名为f的浮点型变量,并赋值为3.14
var c complex128 = 1 + 2i // 声明一个名为c的复数型变量,并赋值为1+2i
var b bool = true // 声明一个名为b的布尔型变量,并赋值为true
var s string = "Hello" // 声明一个名为s的字符串型变量,并赋值为"Hello"
  • 复合类型:复合类型是由基本类型或其他复合类型组合而成的类型,如数组、切片、映射、结构体、接口、函数等。例如:
var arr [5]int = [5]int{1, 2, 3, 4, 5} // 声明一个名为arr的数组变量,并赋值为[1, 2, 3, 4, 5]
var slice []int = arr[1:3] // 声明一个名为slice的切片变量,并赋值为arr的第二个到第三个元素
var m map[string]int = map[string]int{"one": 1, "two": 2} // 声明一个名为m的映射变量,并赋值为{"one": 1, "two": 2}
type Person struct { // 定义一个名为Person的结构体类型
  name string // 定义一个名为name的字符串字段
  age int // 定义一个名为age的整型字段
}
var p Person = Person{"Alice", 20} // 声明一个名为p的Person类型变量,并赋值为{"Alice", 20}
type Animal interface { // 定义一个名为Animal的接口类型
  Speak() string // 定义一个名为Speak的方法,返回一个字符串
}
type Dog struct {} // 定义一个名为Dog的结构体类型
func (d Dog) Speak() string { // 定义Dog类型的Speak方法,实现Animal接口
  return "Woof"
}
var a Animal = Dog{} // 声明一个名为a的Animal类型变量,并赋值为Dog{}
func add(x int, y int) int { // 定义一个名为add的函数,接受两个整型参数,返回一个整型结果
  return x + y
}
  • 表达式和语句:表达式是由操作数和操作符组成的,可以计算出一个值。语句是由表达式和关键字组成的,可以控制程序的执行流程。GO语言支持以下几种表达式和语句:

    • 算术表达式:算术表达式是用来进行数学运算的,包括加法(+)、减法(-)、乘法(*)、除法(/)、取模(%)、自增(++)和自减(–)等操作符。例如:
x := 10 + 20 // x等于30
y := x / 2 // y等于15
x++ // x等于31
y-- // y等于14

注意:自增和自减操作符只能作为语句使用,不能作为表达式使用。例如,x := y++是不合法的。

  • 关系表达式:关系表达式是用来比较两个操作数的大小或相等性的,包括等于(==)、不等于(!=)、大于(>)、小于(<)、大于等于- 关系表达式:关系表达式是用来比较两个操作数的大小或相等性的,包括等于(==)、不等于(!=)、大于(>)、小于(<)、大于等于(>=)和小于等于(<=)等操作符。例如:
x := 10
y := 20
fmt.Println(x == y) // 输出false
fmt.Println(x != y) // 输出true
fmt.Println(x > y) // 输出false
fmt.Println(x < y) // 输出true
fmt.Println(x >= y) // 输出false
fmt.Println(x <= y) // 输出true
  • 逻辑表达式:逻辑表达式是用来进行布尔运算的,包括逻辑与(&&)、逻辑或(||)和逻辑非(!)等操作符。例如:
x := true
y := false
fmt.Println(x && y) // 输出false
fmt.Println(x || y) // 输出true
fmt.Println(!x) // 输出false
fmt.Println(!y) // 输出true
  • 赋值语句:赋值语句是用来给变量或常量赋值的,可以使用等号(=)或者赋值运算符(+=、-=、*=、/=、%=等)来进行赋值。例如:
x := 10 // 使用短变量声明符给x赋值为10
y = 20 // 使用等号给y赋值为20
x += 10 // 使用赋值运算符给x加上10,相当于x = x + 10
y /= 2 // 使用赋值运算符给y除以2,相当于y = y / 2
  • 控制流语句:控制流语句是用来控制程序的执行流程的,包括条件语句(if、else)、选择语句(switch、case)、循环语句(for、break、continue)、跳转语句(goto、label)、返回语句(return)和延迟语句(defer)等。例如:
// 条件语句:根据条件判断执行不同的分支
if x > 0 {
  fmt.Println("x is positive")
} else if x < 0 {
  fmt.Println("x is negative")
} else {
  fmt.Println("x is zero")
}
​
// 选择语句:根据表达式的值选择执行不同的分支,可以省略break,默认执行完一个分支后退出
switch x {
case 1:
  fmt.Println("x is one")
case 2:
  fmt.Println("x is two")
default:
  fmt.Println("x is neither one nor two")
}
​
// 循环语句:重复执行一段代码,直到满足退出条件,可以使用break退出循环,使用continue跳过本次循环
for i := 0; i < 10; i++ { // for循环有三个部分:初始化、条件和更新,可以省略任意部分,甚至全部省略,形成无限循环
  if i == 5 {
    break // 当i等于5时,退出循环
  }
  if i % 2 == 0 {
    continue // 当i是偶数时,跳过本次循环
  }
  fmt.Println(i) // 打印i的值,输出1,3
}
​
// 跳转语句:跳转到指定的标签处执行代码,一般不推荐使用,容易造成代码混乱和难以维护
LOOP: // 定义一个名为LOOP的标签
for i := 0; i < 10; i++ {
  for j := 0; j < 10; j++ {
    if i + j == 10 {
      fmt.Println(i, j) // 打印i和j的值,
       goto LOOP // 跳转到LOOP标签处,结束双重循环
}
} }
​
// 返回语句:用来从函数中返回一个或多个结果,如果没有结果,可以省略返回值 func add(x int, y int) int { // 定义一个名为add的函数,接受两个整型参数,返回一个整型结果 return x + y // 返回x和y的和 }func swap(x int, y int) (int, int) { // 定义一个名为swap的函数,接受两个整型参数,返回两个整型结果 return y, x // 返回x和y的交换值 }func hello() { // 定义一个名为hello的函数,没有参数,也没有返回值 fmt.Println(“Hello”) // 打印"Hello" return // 省略返回值,只表示结束函数 }// 延迟语句:用来延迟执行一段代码,直到函数返回时才执行,常用于释放资源或恢复状态等 func readFile(filename string) { f, err := os.Open(filename) // 打开文件 if err != nil { panic(err) // 如果出错,抛出异常 } defer f.Close() // 延迟关闭文件,无论函数正常返回还是异常退出,都会执行 // 读取文件内容并处理 }

GO语言的实践验证

为了验证GO语言的基本语法和功能,我使用了课程提供的源码(github.com/wangkechun/…)进行了实践。我在本地安装了GO语言的开发环境,并使用Visual Studio Code作为编辑器。我按照课程的顺序,运行了每个示例程序,并观察了输出结果和运行效果。我也尝试了修改一些代码,以加深对GO语言的理解和掌握。

以下是我运行和修改的一些示例程序:

  • hello-world.go:这是一个最简单的GO语言程序,只打印"Hello World"。我修改了打印的内容,改为"Hello GO"。
package main
​
import "fmt"func main() {
    fmt.Println("Hello GO")
}
  • values.go:这是一个展示GO语言中一些基本类型和值的程序。我修改了一些变量的值,并添加了一些注释。
package main
​
import "fmt"func main() {
​
    // 字符串可以用+连接
    fmt.Println("go" + "lang")
​
    // 整数和浮点数
    fmt.Println("1+1 =", 1+1)
    fmt.Println("7.0/3.0 =", 7.0/3.0)
​
    // 布尔值,可以用逻辑运算符操作
    fmt.Println(true && false)
    fmt.Println(true || false)
    fmt.Println(!true)
}
  • variables.go:这是一个展示GO语言中如何声明变量和常量的程序。我修改了一些变量和常量的名字和值,并添加了一些注释。
package main
​
import "fmt"func main() {
​
    // 使用var声明一个变量,可以指定类型,也可以省略类型让编译器推断
    var a string = "initial"
    fmt.Println(a)
​
    var b, c int = 1, 2 // 可以同时声明多个变量,并赋值
    fmt.Println(b, c)
​
    var d = true // 省略类型,编译器推断为布尔型
    fmt.Println(d)
​
    var e int // 声明一个变量但不赋值,会有一个零值,整型的零值是0
    fmt.Println(e)
​
    f := "short" // 使用短变量声明符:=来声明并赋值一个变量,编译器推断类型为字符串
fmt.Println(f)
// 使用const声明一个常量,不能使用:=
const g = "constant"
fmt.Println(g)
// 常量可以进行一些数学运算,但不能修改值
const n = 500000000
const m = 3e20 / n
fmt.Println(m)
// 常量可以根据上下文转换类型,例如,这里m被转换为int64类型
fmt.Println(int64(m))
// 一些数学函数需要显式转换类型,例如,这里n被转换为float64类型
fmt.Println(math.Sin(float64(n)))
}
  • for.go:这是一个展示GO语言中如何使用for循环的程序。我修改了一些循环的条件和操作,并添加了一些注释。
package main
​
import "fmt"func main() {
​
    // 最基本的for循环,有三个部分:初始化、条件和更新
    i := 1 // 初始化
    for i <= 3 { // 条件
        fmt.Println(i) // 循环体
        i = i + 1 // 更新
    }
​
    // 可以省略初始化和更新部分,相当于其他语言的while循环
    for j := 4; j <= 6; j++ {
        fmt.Println(j)
    }
​
    // 可以省略所有的部分,形成一个无限循环,需要用break或return退出循环
    for {
        fmt.Println("loop")
        break // 退出循环
    }
​
    // 可以使用continue跳过本次循环,继续下一次循环
    for n := 0; n <= 10; n++ {
        if n%2 == 0 { // 如果n是偶数
            continue // 跳过本次循环
        }
        fmt.Println(n) // 打印n的值,输出1,3,5,7,9
    }
}

GO语言的个人思考

通过学习和实践GO语言的基础语法,我对GO语言有了以下几点思考:

  • GO语言是一种简洁、高效、可靠和跨平台的编程语言,适合开发各种规模和领域的应用程序。GO语言的设计哲学是“少即是多”,即通过减少不必要的特性和复杂度,提高编程的效率和质量。
  • GO语言的语法和C语言有很多相似之处,但也有很多改进和创新。例如,GO语言没有指针运算、类型转换、继承和泛型等特性,避免了一些潜在的错误和混乱。GO语言也引入了一些新的特性,如切片、映射、接口和goroutine等,增加了编程的灵活性和高效性。
  • GO语言的并发支持是其最大的亮点之一,通过goroutine和通道来实现轻量级的线程和数据交互。goroutine可以在一个操作系统线程上运行多个goroutine,实现高并发和低开销。通道是一种同步的消息传递机制,可以在不同的goroutine之间安全地传递数据。GO语言的并发模型遵循了“不要通过共享内存来通信,而要通过通信来共享内存”的原则,简化了并发编程的难度和风险。
  • GO语言的标准库提供了一套完善的功能模块,涵盖了常用的数据结构、算法、网络、数据库、测试、加密等功能。标准库的接口设计遵循了统一和简洁的原则,易于学习和使用。GO语言的标准库也是GO语言的最佳实践,可以从中学习到GO语言的编程风格和技巧。

总之,GO语言是一门值得学习和使用的编程语言,它可以帮助我提高编程的能力和水平,也可以让我开发出更好的应用程序。我希望通过这门课程,能够更深入地了解和掌握GO语言的知识和技能,也能够将GO语言应用到实际的项目中去。