下面就是完整的程序。点击运行。
这几行一行都不能少。本页其余部分会解释每一行的作用。
逐行讲解
package main
每个 Go 文件都以 package 子句开头,写明它属于哪个包。main 这个名字很特殊:它把这个包标记为可执行程序。换成任何其他名字(package utils、package hello)都会得到一个库,其他代码可以导入它,但它本身不能运行。
import "fmt"
import 引入另一个包,让你可以使用它。fmt 是标准库中负责格式化和打印的包。导入之后,它导出的名字要通过包名来访问:fmt.Println、fmt.Printf、fmt.Sprintf。
要导入多个包,就用一个圆括号块,每行写一个路径:
import (
"fmt"
"strings"
)
如果一个文件导入了某个包却没有使用,Go 会拒绝编译。这让依赖列表始终如实,也是大多数人遇到的第一个错误。
func main()
func 用来声明函数。main 包里的 main 函数是程序的入口:main 开始时程序开始,main 返回时程序结束。它不接收参数,也不返回任何值。命令行参数来自 os.Args,退出码则通过 os.Exit 设置。
fmt.Println("Hello, World!")
Println 打印它的参数,在参数之间加空格,并在末尾加换行。这个名字以大写字母开头,是因为只有首字母大写的名字才会从包中导出。把 p 写成小写的 fmt.println 会导致编译错误。
打印的不止是字符串
Println 可以接收任意数量、任意类型的值。Printf 则让你自己控制格式:
%s 会被替换成字符串,%d 会被替换成整数。Printf 和 Print 不会自动换行,所以 \n 要你自己写。完整的格式动词表在 fmt.Printf 页面。
在你的电脑上运行
装好 Go 之后,把程序保存为空文件夹里的 main.go,然后运行:
go run main.go
Hello, World!
go run 会把文件编译成一个临时的二进制文件并运行它。要生成一个可以保留、可以复制到别处的二进制文件,就用 go build:
go mod init example.com/hello
go build
./hello
Hello, World!
go build 需要一个模块(也就是 go.mod 文件),由 go mod init 创建。生成的二进制文件以模块路径的最后一段命名,这里是 hello(在 Windows 上是 hello.exe)。run、build 和 install 的区别在 go run 和 go build 页面中讲解。
分号去哪了
Go 的语法里有分号,但你几乎从来不用自己输入。编译器会在每一行的末尾插入分号,只要这一行的最后一个记号可能结束一条语句:标识符、字面量、)、},以及 return 等少数几个关键字。正是这条规则,让其他语言里常见的这种写法在 Go 里行不通:
func main()
{
fmt.Println("Hello, World!")
}
./main.go:6:1: syntax error: unexpected semicolon or newline before {
func main() 之后被插入了一个分号,所以下一行的 { 就成了错误。左花括号总是写在同一行。if、for、switch 以及其他所有代码块都遵循同样的规则。
最初的错误,逐一解释
下面是新手在第一个小时里会看到的报错,与 Go 1.24 打印的内容一字不差。
未使用的导入或变量。
package main
import (
"fmt"
"os"
)
func main() {
x := 5
fmt.Println("hi")
}
./main.go:5:2: "os" imported and not used
./main.go:9:2: declared and not used: x
这两个都是编译错误,不是警告。删掉这个导入或变量即可。如果调试时需要暂时保留某个变量,就把它赋给空白标识符:_ = x。
函数名写成了小写。
./main.go:6:6: undefined: fmt.println
未导出的名字在包外不可见。请使用 fmt.Println。
包名写错了。
package example.com/hello is not a main package
文件里写的是 package hello(或者 main 以外的任何名字),而你试图运行它。把它改成 package main。
缺少模块。
go: go.mod file not found in current directory or any parent directory; see 'go help modules'
go build 和 go run . 都基于模块工作。在这个文件夹里运行一次 go mod init example.com/hello 即可。直接指定文件名的 go run main.go 不需要模块也能运行。
代码格式化
Go 只有一种官方代码风格,由 gofmt 来统一。对你写的每个文件都运行它:
go fmt ./...
它使用 Tab 缩进,对齐注释和结构体字段,并统一空格。支持 Go 的编辑器会在保存时自动运行它。所有 Go 代码看起来都一样,所以没有什么需要配置,代码评审时也没有什么好争论的。
常见问题
Go 语言怎么写 hello world?
把下面的代码保存为 main.go:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
然后运行 go run main.go,它会打印 Hello, World!。
为什么 Go 程序需要 package main?
package main 告诉编译器这个包是一个可执行程序,而不是库。程序从 main 包的 main 函数开始运行。换成任何其他包名都会得到一个库,go run 会拒绝运行它,并提示“is not a main package”。
为什么 Go 的左花括号必须写在同一行?
Go 会在可能结束一条语句的行尾自动插入分号,func main() 之后也是如此。这样下一行的 { 就会开始一个独立的块,编译器会报告 syntax error: unexpected semicolon or newline before {。所以左花括号必须写在同一行。
Go 里的 fmt 是什么意思?
fmt 是标准库中负责格式化输入输出的包(名字是“format”的缩写)。fmt.Println 打印它的参数,参数之间用空格隔开,末尾加换行;fmt.Printf 则按格式字符串打印。