ZetCode

Go 基础知识

最后修改时间 2024 年 4 月 11 日

本文介绍 Go 语言的基本编程概念。

Go 是一种开源编程语言,可以轻松构建简单、可靠且高效的软件。Go 是一种由 Google 创建的静态类型、编译型编程语言。

标识符

标识符是变量、函数、类或参数的名称。标识符可以包含字母数字字符和下划线。变量名不能以数字开头。名称中不允许使用空格。

标识符是区分大小写的。这意味着 Name、name 和 NAME 指的是三个不同的变量。标识符也不能与语言关键字冲突。

Go 空白符

Go 中的空白符用于分隔程序中的标记。它也用于提高源代码的可读性。

var i int = 0

在某些地方需要空白符。例如,在 i 变量和 int 关键字之间。在其他地方,禁止使用空白符。它们不能出现在变量标识符或语言关键字中。

var i int=1
var j int = 2
var k int  =  3

标记之间的空格量对于 Go 编译器无关紧要。应在 Go 程序中一致使用空格。

第一个示例

我们创建第一个示例。

$ mkdir first
$ cd first

我们创建一个项目目录并切换到那里。

$ go mod init zetcode.com/first

我们初始化一个 Go 模块。

main.go
package main

import "fmt"

func main() {

    fmt.Println("Go first example")
}

这是一个简单的 Go 程序,它将消息打印到控制台。

package main

Go 代码组织在包中。程序在 main 包中开始运行。

import "fmt"

使用 import 关键字将包包含到程序中。fmt 包包含具有格式化 I/O 的函数。

func main() {

在 main 包中,main 函数是 Go 程序的入口点。使用 func 关键字创建函数。

fmt.Println("Go first example")

fmt 包中,我们使用 Println 函数显示消息。请注意,语句不像 Java、C 或 C# 等语言那样以分号结尾。

$ go run main.go
Go first example

我们使用 go run 命令一次性编译和执行程序。

注释

注释用于人类来澄清源代码。Go 中有两种类型的注释:单行注释(//)和多行注释(/* */)。

main.go
package main

import "fmt"

/*
  This is comments.go
  Author: Jan Bodnar
  ZetCode 2024
*/

// Program starts here
func main() {
    fmt.Println("Go first example")
}

在代码示例中,我们有一个多行注释和一个单行注释。编译器会忽略注释。

变量

变量用于存储值。它是给值的标签。Go 使用 var 关键字来声明变量列表。我们也可以使用 := 简写语法来声明变量。

变量可以保存不同数据类型的值。数据类型是一组值以及对这些值允许的操作。在许多情况下,Go 可以从赋值的右侧推断出数据类型。

main.go
package main

import "fmt"

func main() {

    var i int = 1
    var w float64 = 12.5

    fmt.Println(i, w)
}

在代码示例中,我们声明并初始化了两个变量,然后打印它们。第一个变量存储一个整数,第二个变量存储一个浮点数。在 Go 中,数据类型跟在变量名后面。

类型推断

Go 可以从赋值的右侧推断出数据类型。

main.go
package main

import (
    "fmt"
    "reflect"
)

func main() {

    var name = "John Doe"
    var age = 34

    fmt.Println(reflect.TypeOf(name))
    fmt.Println(reflect.TypeOf(age))

    fmt.Printf("%s is %d years old\n", name, age)
}

在代码示例中,我们定义了两个变量而没有指定它们的数据类型。数据类型是推断出来的。

var name = "John Doe"
var age = 34

为了让推断起作用,变量必须初始化

fmt.Println(reflect.TypeOf(name))
fmt.Println(reflect.TypeOf(age))

借助 reflect 包中的 TypeOf 函数,我们打印出两个变量的数据类型。

$ go run main.go
string
int
John Doe is 34 years old

简写变量声明

在函数内部,可以使用 := 简短赋值语句代替带有隐式类型的 var 声明。

main.go
package main

import "fmt"

func main() {

    name := "John Doe"
    age := 34

    fmt.Println("%s is %d years old", name, age)
}

该示例使用简写表示法声明了两个变量。

用户输入

Scanf 函数读取标准输入中的文本,并根据格式将连续的空格分隔的值存储到连续的参数中。它返回成功扫描的项目数。

main.go
package main

import "fmt"

func main() {

    var name string

    fmt.Print("Enter your name: ")
    fmt.Scanf("%s", &name)
    fmt.Println("Hello", name)
}

该示例提示用户输入名字。

var name string

我们定义一个字符串变量。

fmt.Scanf("%s", &name)

输入的价值被存储在 name 变量中。

$ go run main.go
Enter your name: Robert
Hello Robert

我们运行程序并输入一个名字。

条件语句

条件语句使用 ifelse ifelse 关键字创建。

main.go
package main

import (
    "fmt"
    "math/rand"
)

func main() {

    num := -5 + rand.Intn(10)

    if num > 0 {

        fmt.Println("The number is positive")
    } else if num == 0 {

        fmt.Println("The number is zero")
    } else {

        fmt.Println("The number is negative")
    }
}

在本例中,我们生成一个介于 -5 和 4 之间的随机值。借助条件语句,我们为所有三个选项打印一条消息。

for 循环

for 语句指定块的重复执行。

main.go
package main

import "fmt"

func main() {

    sum := 0

    for i := 0; i < 10; i++ {
        sum += i
    }

    fmt.Println(sum)
}

这是经典的 C 风格 for 语句。该程序计算 1..9 的值之和。

for i := 0; i < 10; i++ {
    sum += i
}

for 语句包含三个部分:初始化、条件和增量。初始化部分仅执行一次。当条件为真时,执行 for 语句的主体。如果条件返回 false,则 for 循环终止。

在执行完块中的语句后,for 循环会进入第三部分,其中计数器会增加。循环继续,直到条件不再为真。请注意,可能创建无限循环。

$ go run main.go
45

1..9 的值之和为 45。

以下示例使用带 range 关键字的 for 循环。

main.go
package main

import "fmt"

func main() {

    nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

    sum := 0

    for _, num := range nums {
        sum += num
    }

    fmt.Println(sum)
}

该示例计算数组值的总和。

nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

我们定义了一个值数组。

for _, num := range nums {
    sum += num
}

我们使用 range 子句迭代数组。range 在每次迭代中返回索引和值。由于我们不使用索引,我们指定了丢弃符 _。(Go 文档称之为空白标识符。)

Switch 语句

Go switch 语句提供多路执行。将表达式或类型说明符与 switch 中的 case 进行比较,以确定执行哪个分支。与其他语言(如 C、Java 或 PHP)不同,每个 case 都由隐式的 break 终止;因此,我们不必显式编写它。

default 语句可用于在没有其他 case 匹配时执行的分支。default 语句是可选的。

main.go
package main

import (
    "fmt"
    "runtime"
)

func main() {
    os := runtime.GOOS
    switch os {
    case "windows":
        fmt.Println("Windows")
    case "darwin":
        fmt.Println("MAC operating system")
    case "linux":
        fmt.Println("Linux")
    default:
        fmt.Printf("%s.\n", os)
    }
}

GOOS 环境变量是正在运行的程序的操作系统目标:可能是 darwin、freebsd、linux 等。根据变量的值,我们打印操作系统版本。

$ go run main.go 
Linux

命令行参数

命令行参数是传递给程序的选项和数据。我们通常将参数传递给控制台程序,但有时也传递给 GUI 程序。

os.Args 包含命令行参数。此切片中的第一个值是程序名称,而 os.Args[1:] 包含传递给程序的参数。可以通过索引操作访问各个参数。

main.go
package main

import (
    "fmt"
    "os"
    "reflect"
)

func main() {

    prg_name := os.Args[0]
    fmt.Printf("The program name is %s\n", prg_name)

    names := os.Args[1:]
    fmt.Println(reflect.TypeOf(names))

    for _, name := range names {

        fmt.Printf("Hello, %s!\n", name)
    }
}

该示例接收命令行参数。

prg_name := os.Args[0]
fmt.Printf("The program name is %s\n", prg_name)

我们获取并打印第一个参数,即程序名称。

names := os.Args[1:]

我们获取所有接收到的参数。

fmt.Println(reflect.TypeOf(names))

我们打印持有参数的类型(切片)。

for _, name := range names {

    fmt.Printf("Hello, %s!\n", name)
}

我们遍历参数并从每个参数构建一条消息。

$ go build main.go 
$ ./main Jan Peter Lucia
The program name is main
[]string
Hello, Jan!
Hello, Peter!
Hello, Lucia!

我们构建程序并运行它。我们在命令行上传递了三个名字给程序。

函数

函数是将零个或多个输入参数映射到零个或多个输出参数。Go 函数是头等公民。函数可以赋值给变量、作为参数传递给函数或从函数返回。

Go 中的函数使用 func 关键字创建。我们使用 return 关键字从函数返回。函数体包含函数调用时执行的语句。函数体用一对花括号 {} 分隔。要调用函数,我们指定其名称后跟圆括号 ()。函数可以接受参数,也可以不接受参数。

main.go
package main

import "fmt"

func main() {

    x := 4
    y := 5

    z := add(x, y)

    fmt.Printf("Output: %d\n", z)
}

func add(a int, b int) int {

    return a + b
}

在代码示例中,我们定义了一个将两个值相加的函数。

z := add(x, y)

我们调用 add 函数;它接受两个参数。计算出的值传递给 z 变量。

func add(a int, b int) int {

    return a + b
}

我们定义 add 函数。函数参数用逗号分隔;每个参数名后跟其数据类型。在参数之后,我们指定返回值类型。调用函数时执行的语句放在花括号之间。加法操作的结果使用 return 关键字返回给调用者。

$ go run main.go 
Output: 9

来源

The Go Programming Language Specification

本文介绍了 Go 语言的基础知识。

作者

我叫 Jan Bodnar,是一名热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程