第一个 Go 程序:Hello World

Go 编程实战系列(四)

在前面的文章中,我们已经完成了 Go 开发环境安装,并配置了 GoLand 或 VS Code。接下来,我们将正式编写第一个 Go 程序。

几乎每一种编程语言的学习,都会从"Hello World"开始。虽然这个程序非常简单,但它包含了 Go 可执行程序最基本的组成部分,例如包声明、依赖导入、主函数和标准输出。

本文不仅会带你运行 Hello World,还会逐行分析代码,并介绍 Go 程序从源码到运行结果的完整过程。


一、创建 Go 项目

首先选择一个用于保存项目的目录。

例如,在终端中执行:

bash 复制代码
mkdir hello-go
cd hello-go

Windows 用户也可以在某个磁盘下创建项目:

go 复制代码
mkdir D:\go-projects\hello-go
cd D:\go-projects\hello-go

进入项目目录后,执行:

go 复制代码
go mod init hello-go

终端会输出:

go 复制代码
go: creating new go.mod: module hello-go

此时项目目录中会生成一个 go.mod 文件:

go 复制代码
hello-go
└── go.mod

go.mod 是 Go Modules 的核心文件,用于记录当前项目的模块名称、Go 版本以及第三方依赖。

文件内容大致如下:

go 复制代码
module hello-go

go 1.xx

其中,module hello-go 表示当前项目的模块名称。

关于 Go Modules 的详细内容,我们会在下一篇文章中专门讲解。


二、创建 main.go 文件

在项目根目录中新建一个名为 main.go 的文件。

项目结构变为:

go 复制代码
hello-go
├── go.mod
└── main.go

main.go 中写入以下代码:

go 复制代码
package main

import "fmt"

func main() {
	fmt.Println("Hello World")
}

保存文件后,在终端执行:

arduino 复制代码
go run .

输出结果为:

复制代码
Hello World

至此,第一个 Go 程序已经成功运行。


三、逐行分析 Hello World

虽然代码只有几行,但每一部分都有明确的作用。

1. package main

第一行代码是:

css 复制代码
package main

Go 使用包组织代码,每一个 Go 源文件都必须声明自己属于哪个包。

这里的包名是:

css 复制代码
main

main 是一个特殊的包名。

当一个项目需要编译成可以直接运行的程序时,必须包含 main 包,同时还必须包含一个 main 函数。

例如:

go 复制代码
package main

func main() {
}

如果使用其他包名,例如:

go 复制代码
package hello

这个包通常会被当作代码库使用,不能直接作为独立程序运行。

因此,可以简单理解为:

  • package main:表示这是一个可执行程序;

  • 其他包名:通常表示这是一个可以被其他代码调用的功能包。


2. import "fmt"

第二部分代码是:

arduino 复制代码
import "fmt"

import 用于导入其他包。

这里导入的是 Go 标准库中的 fmt 包。fmt 是 format 的缩写,主要用于格式化输入和输出。

它提供了很多常用函数,例如:

scss 复制代码
fmt.Print()
fmt.Println()
fmt.Printf()
fmt.Sprintf()
fmt.Scan()

其中:

  • Print:输出内容,不自动换行;

  • Println:输出内容并自动换行;

  • Printf:按照指定格式输出;

  • Sprintf:格式化字符串并返回结果;

  • Scan:读取用户输入。

在当前程序中,我们使用了:

arduino 复制代码
fmt.Println("Hello World")

因此必须先导入 fmt 包。

如果删除导入语句,程序就会报错:

bash 复制代码
undefined: fmt

因为编译器不知道 fmt 是什么。


3. func main()

接下来是:

csharp 复制代码
func main() {
}

func 是定义函数的关键字。

基本格式如下:

go 复制代码
func 函数名() {
	函数代码
}

这里定义的函数名为 main

main 函数是 Go 可执行程序的入口。当程序启动时,会自动从 main 函数开始执行。

需要注意,main 函数必须满足以下条件:

  • 必须位于 main 包中;

  • 函数名必须是 main

  • 不能带参数;

  • 不能声明返回值。

正确写法:

csharp 复制代码
func main() {
}

下面的写法不能作为程序入口:

csharp 复制代码
func Main() {
}

Go 区分大小写,Mainmain 是两个不同的名称。


4. fmt.Println()

函数中的代码是:

arduino 复制代码
fmt.Println("Hello World")

这行代码调用了 fmt 包中的 Println 函数。

在 Go 中,调用其他包中的公开函数,通常采用以下格式:

scss 复制代码
包名.函数名()

因此:

scss 复制代码
fmt.Println()

表示调用 fmt 包中的 Println 函数。

括号中的:

arduino 复制代码
"Hello World"

是一个字符串。

Go 字符串通常使用双引号包裹:

arduino 复制代码
"你好,Go"
arduino 复制代码
"学习 Go 编程"
arduino 复制代码
"Hello World"

程序运行后,字符串会被输出到终端。


四、使用 go run 运行程序

运行 Go 程序最简单的方式是:

arduino 复制代码
go run .

这里的点号表示当前目录。

Go 会找到当前目录中的 Go 源文件,临时完成编译,然后运行程序。

也可以直接指定文件:

go 复制代码
go run main.go

对于当前只有一个文件的项目,两种方式都可以。

但随着项目规模扩大,一个项目中可能包含多个 Go 文件。因此,更推荐使用:

arduino 复制代码
go run .

需要注意,go run 主要用于开发和测试。它不会在当前目录中留下最终的可执行文件。


五、使用 go build 编译程序

除了直接运行,还可以将 Go 源代码编译成可执行程序:

go 复制代码
go build

编译完成后,当前目录会生成可执行文件。

Windows 系统通常生成:

go 复制代码
hello-go.exe

macOS 和 Linux 通常生成:

go 复制代码
hello-go

在 Windows 中运行:

go 复制代码
.\hello-go.exe

在 macOS 或 Linux 中运行:

bash 复制代码
./hello-go

输出同样是:

复制代码
Hello World

还可以使用 -o 参数指定生成的文件名称:

go 复制代码
go build -o hello

Windows 下可以执行:

go 复制代码
go build -o hello.exe

go buildgo run 的主要区别是:

  • go run:临时编译并立即运行;

  • go build:生成可长期保存和部署的可执行文件。

Go 编译出的程序通常不需要目标服务器额外安装 Go 环境,这也是 Go 部署方便的重要原因。


六、修改输出内容

可以尝试修改程序,让它输出多行内容:

go 复制代码
package main

import "fmt"

func main() {
	fmt.Println("Hello World")
	fmt.Println("这是我的第一个 Go 程序")
	fmt.Println("开始学习 Go 编程")
}

运行:

arduino 复制代码
go run .

输出:

复制代码
Hello World
这是我的第一个 Go 程序
开始学习 Go 编程

也可以在一次调用中传入多个内容:

go 复制代码
package main

import "fmt"

func main() {
	name := "Go"
	fmt.Println("Hello", name)
}

输出:

复制代码
Hello Go

Println 会在多个参数之间自动添加空格,并在末尾自动换行。


七、使用 Printf 格式化输出

除了 Println,开发中还经常使用 Printf

示例:

go 复制代码
package main

import "fmt"

func main() {
	name := "Go"
	year := 2009

	fmt.Printf("%s 语言于 %d 年正式发布\n", name, year)
}

运行结果:

yaml 复制代码
Go 语言于 2009 年正式发布

这里使用了格式占位符:

  • %s:字符串;

  • %d:整数;

  • \n:换行。

Printf 不会像 Println 一样自动换行,所以通常需要手动加入 \n


八、Go 代码为什么不需要分号?

学习过 C、C++、Java 或 JavaScript 的开发者,可能会发现 Go 代码末尾没有分号:

arduino 复制代码
fmt.Println("Hello World")

而不是:

arduino 复制代码
fmt.Println("Hello World");

实际上,Go 语法内部仍然存在分号规则,但编译器通常会自动补充,因此开发者不需要手动书写。

统一省略分号能够让代码更加简洁,也能减少不一致的代码风格。


九、Go 对代码格式的要求

Go 非常强调统一的代码格式。

例如,下面的代码虽然看起来很乱:

go 复制代码
package main
import "fmt"
func main(){fmt.Println("Hello World")}

但执行格式化命令:

css 复制代码
gofmt -w main.go

之后会自动变为:

go 复制代码
package main

import "fmt"

func main() {
	fmt.Println("Hello World")
}

如果使用 GoLand 或 VS Code,还可以开启保存时自动格式化。

Go 官方通过 gofmt 统一代码风格,使不同开发者编写的代码保持相似结构,降低团队协作和代码阅读成本。


十、常见错误

1. 找不到 go.mod

执行 go run . 时可能提示:

go 复制代码
go: go.mod file not found

解决方法是在项目目录执行:

go 复制代码
go mod init hello-go

2. package 拼写错误

错误代码:

css 复制代码
pakage main

正确代码:

css 复制代码
package main

Go 关键字不能随意拼写。


3. main 函数大小写错误

错误写法:

csharp 复制代码
func Main() {
}

正确写法:

csharp 复制代码
func main() {
}

Go 区分大小写。


4. 导入了包却没有使用

例如:

go 复制代码
package main

import "fmt"

func main() {
}

运行时会提示:

arduino 复制代码
"fmt" imported and not used

Go 不允许存在未使用的导入包。要么使用 fmt,要么删除导入语句。


5. 字符串使用了错误引号

错误写法:

scss 复制代码
fmt.Println("Hello World")

这里使用的是中文弯引号,Go 无法识别。

正确写法:

arduino 复制代码
fmt.Println("Hello World")

编写代码时必须使用英文符号。


十一、本章小结

本篇完成了第一个 Go 程序 Hello World,并分析了 Go 可执行程序的基本结构。

主要知识点包括:

  • 使用 go mod init 初始化项目;

  • 使用 package main 声明可执行程序;

  • 使用 import 导入标准库;

  • main 函数是程序入口;

  • 使用 fmt.Println 输出内容;

  • 使用 go run . 运行程序;

  • 使用 go build 编译可执行文件;

  • 使用 gofmt 格式化代码;

  • Go 不允许存在未使用的导入包。

Hello World 虽然简单,却包含了 Go 程序最核心的基本结构。后续无论开发命令行工具、Web 服务还是微服务项目,都将从类似的代码结构开始。


本章练习

  1. 创建一个名为 hello-go 的项目。
  2. 初始化项目并生成 go.mod
  3. 使用 Println 输出姓名和学习目标。
  4. 使用 Printf 输出一个字符串和一个整数。
  5. 使用 go run . 运行程序。
  6. 使用 go build 编译程序。
  7. 使用 gofmt 格式化代码。
  8. 故意导入一个未使用的包,观察编译器提示。

下一篇预告

《Go Modules 包管理详解》

下一篇将介绍现代 Go 项目的依赖管理方式,包括 go.modgo.sum、模块路径、依赖下载、版本管理、go getgo mod tidy、模块代理以及常见依赖问题的解决方法。

相关推荐
阳光是sunny1 小时前
LangGraph 核心概念详解:从编译到可视化
前端·人工智能·后端
zhangjw341 小时前
第35篇:Spring Boot入门:自动配置+快速搭建,简化企业开发
java·spring boot·后端
名字还没想好☜1 小时前
Go 的 select 实战:超时、非阻塞收发与优雅退出的三个套路
开发语言·数据库·golang·go·并发
geovindu1 小时前
java: Backtracking Algorithm
java·开发语言·windows·后端·算法·回溯算法
不好听6132 小时前
React 父子组件通信:从 Todo 应用理解单向数据流
前端·react.js
_lucas2 小时前
做了一个glsl在线调试工具
前端·javascript·three.js
lazy H2 小时前
从入门到日常开发,一篇文章掌握 Git 核心操作
git·后端·学习·github
不好听61310 小时前
从一行 JSX 到屏幕像素:前端开发者必须懂的浏览器渲染管线
前端
恒拓高科WorkPlus10 小时前
企业级内网即时通讯建设模型:BeeWorks内网IM四层架构
前端