news 2026/6/18 17:35:56

Go 入门到精通-03-第一个程序Hello World

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Go 入门到精通-03-第一个程序Hello World

🟢 基础入门 | Go 入门到精通 2026(三):第一个程序 Hello World

📅 更新于 2026年6月 | ✍️ 原创文章,转载请注明出处 | 作者:布朗克168



开篇

编程界的传统:学任何新语言,第一个程序必须是Hello World。这不是形式主义——一个简单的 Hello World 背后,藏着语言的程序结构、编译模型和运行机制。

🎯 本文目标:写完 Hello World 后,你能理解每一个关键字和每一行代码在做什么,而不只是"运行成功就行"。


1. 创建你的第一个 Go 程序

步骤 1:创建项目目录

mkdir~/go-projects/hellocd~/go-projects/hello

步骤 2:初始化 Go Module

go mod init hello

步骤 3:创建 main.go

touchmain.go

用你喜欢的编辑器打开main.go,输入以下代码:

packagemainimport"fmt"funcmain(){fmt.Println("Hello, World! 🌍")fmt.Println("欢迎来到 Go 语言的世界!")}

步骤 4:运行

$ go run main.go Hello, World!🌍 欢迎来到 Go 语言的世界!

🎉 恭喜!你已经是一个 Go 程序员了(至少是初级的)。


2. 完整程序结构逐行分析

让我们把上面的 6 行代码拆开了揉碎了看:

packagemain
要素说明
packageGo 的关键字,声明当前文件属于哪个包
main特殊的包名,告诉 Go 编译器这是一个可执行程序的入口
位置必须是文件的第一行有效代码(注释除外)

Go 中每个.go文件都必须属于一个包。包名是main时,编译器会把它编译成一个可执行文件;包名是其他名字(如utilmodels)时,编译成库(.a文件)。

import"fmt"
要素说明
import导入其他包的关键字
"fmt"Go 标准库中的格式化 I/O 包(类似 C 的stdio.h

fmt是 Go 最常用的标准库之一,提供了格式化输入输出功能:

  • fmt.Println()— 打印并换行
  • fmt.Printf()— 格式化打印
  • fmt.Scanln()— 读取输入
  • fmt.Sprintf()— 格式化返回字符串

如果需要导入多个包,有两种写法:

// 写法一:多行 import(推荐)import("fmt""os""time")// 写法二:多个单行 import(不推荐)import"fmt"import"os"import"time"
funcmain(){// ...}
要素说明
func声明函数的关键字
main特殊函数名,程序的唯一入口
()参数列表(此处无参数)
{函数体开始(必须和 func 在同一行

⚠️Go 的"左大括号不能换行"规则

// ✅ 正确funcmain(){// ❌ 错误!编译不通过funcmain(){

这是 Go 编译器强制要求的,目的是统一代码风格。

fmt.Println("Hello, World! 🌍")

这里做了两件事:

  1. 调用fmt包的Println函数(注意:Println首字母大写,表示它是公开的/导出的
  2. 传入一个字符串参数"Hello, World! 🌍"

Go 的可见性规则极其简洁:首字母大写 = 公开(exported),首字母小写 = 私有(unexported)。没有public/private/protected关键字。


3. 三种运行方式:go run vs go build vs go install

Go 提供了三种运行代码的方式,各有适用场景:

3.1 go run —— 快速运行

go run main.go
  • 做了什么:编译 + 运行,但不保留编译产物
  • 适用场景:开发调试、快速验证
  • 特点:最方便,但每次都要重新编译
# 可以同时运行多个文件go run main.go helper.go# 运行整个包go run.

3.2 go build —— 编译成二进制

go build main.go# 生成 main(Linux/Mac)或 main.exe(Windows)# 指定输出文件名go build-ohello main.go# 生成 hello 或 hello.exe
  • 做了什么:只编译,不运行,生成可执行文件
  • 适用场景:生产部署、发布
  • 特点:一次编译,到处运行(同平台)
# 编译整个模块go build ./...# 编译并输出到指定目录go build-obin/hello.

3.3 go install —— 编译并安装

goinstall.# 编译并将二进制放到 $GOPATH/bin/ 下
  • 做了什么:编译 + 安装到$GOPATH/bin
  • 适用场景:安装 Go 工具(如goplsstaticcheck
  • 特点:编译产物放在统一位置,方便全局调用

三者的对比

命令编译运行保留产物产物位置最佳场景
go run临时目录开发调试
go build当前目录生产部署
go install$GOPATH/bin工具安装

关于 go build 的更多选项

# 查看编译详情go build-v.# 减小二进制体积(去掉调试信息和符号表)go build-ldflags="-s -w"-ohello.# 查看二进制大小ls-lhhello# -rwxr-xr-x 1 user staff 1.9M hello # 未压缩# -rwxr-xr-x 1 user staff 1.3M hello # 压缩后

4. 编译产物深度分析

让我们深入看看 Go 编译出来的二进制到底是个什么东西。

查看文件信息

# macOS/Linux$filehello hello: Mach-O64-bit executable arm64# Apple Silicon# 或hello: ELF64-bit LSB executable, x86-64# Linux# 查看大小$ls-lhhello -rwxr-xr-x1user staff1.9M hello# 查看依赖的动态库$ otool-Lhello# macOS$ ldd hello# Linux# Go 默认静态链接,通常会输出 "not a dynamic executable"

编译过程简析

Go 的编译过程大体如下:

源代码 (.go) │ ▼ 词法分析 → Token 流 │ ▼ 语法分析 → AST(抽象语法树) │ ▼ 类型检查 │ ▼ 中间代码生成(SSA) │ ▼ 优化 │ ▼ 机器码生成 │ ▼ 链接(静态链接所有依赖) │ ▼ 可执行文件

💡 关键差异:Go 默认静态链接,把运行时(runtime)、垃圾回收器、goroutine 调度器一起打包到二进制里。这就是为什么 Go 程序不需要目标机器安装 Go 环境就能运行。

查看编译过程

# 打印编译过程go build-x.# 查看生成的汇编代码go tool compile-Smain.go# 查看编译器优化决策go build-gcflags="-m".# 输出中会看到逃逸分析等信息

5. go fmt:代码格式化

Go 从诞生之初就内置了代码格式化工具,目的很简单:消灭"代码风格之争"

基本用法

# 格式化单个文件gofmtmain.go# 格式化整个项目gofmt./...# 查看哪些文件需要格式化(不实际修改)gofmt-l.

格式化什么?

把你的代码故意写成这样:

packagemainimport"fmt"funcmain(){x:=1+2fmt.Println(x)}

运行go fmt后:

packagemainimport"fmt"funcmain(){x:=1+2fmt.Println(x)}

自动修复了:

  • 缩进(Tab 缩进)
  • 空格(运算符两边加空格)
  • 空行(import 上下加空行)

goimports:更智能的格式化

goimportsgofmt的基础上,还自动管理 import 语句:

# 安装goinstallgolang.org/x/tools/cmd/goimports@latest# 使用goimports-wmain.go# 自动添加缺失的 import,移除未使用的 import

🔧 VS Code 中设置"go.formatTool": "goimports"后,每次保存都会自动格式化 + 整理 import。


6. 常见编译错误及排查

初学 Go 时,你大概率会遇到以下错误。别怕,我都帮你整理好了:

错误 1:package main is not in GOROOT

package hello/main is not in GOROOT (/usr/local/go/src/hello/main)

原因:Go 在 GOPATH 或 GOROOT 中找不到你的包。

解决

# 确保在项目目录中初始化了 go.modcd~/go-projects/hello go mod init hello

错误 2:main.go:1:1: expected 'package', found 'import'

// ❌ 错误:import 在 package 之前import"fmt"packagemain

解决package声明必须在所有非注释代码的第一行。

// ✅ 正确packagemainimport"fmt"

错误 3:undefined: Println

packagemainfuncmain(){Println("Hello")// ❌ 缺少包名}

解决:调用其他包的公开函数时必须带上包名前缀:

fmt.Println("Hello")// ✅

错误 4:imported and not used: "fmt"

packagemainimport"fmt"// ❌ 导入了但没使用funcmain(){// 什么也没做}

解决:Go 不允许导入未使用的包——这在 Go 中是编译错误,不是警告。

# 删除多余的 import,或者用空白标识符占位import_"fmt"// 仅执行 init 函数,不直接使用

错误 5:syntax error: unexpected semicolon or newline before {

funcmain()// ❌ 左大括号必须在同一行{

解决:Go 编译器会在行末自动插入分号,所以左大括号不能换行。

错误 6:main redeclared in this block

funcmain(){}// ❌ 同一包中只能有一个 main 函数funcmain(){}// ❌ 重复定义

解决:一个main包里只能有一个main函数。

错误速查表

错误信息关键词原因解决办法
expected 'package'package 不在第一行把 package 声明移到第一行
undefined未导入包或未声明检查 import 和变量声明
imported and not used导入了但没使用删除或加_前缀
declared and not used变量声明了但没使用删除或使用它
cannot use类型不匹配检查类型,可能需要显式转换
missing return有返回值的函数缺少 return添加 return 语句

7. go doc:查阅文档

Go 自带文档工具,不需要联网就能查看标准库文档。

基本用法

# 查看包的文档go docfmt# 查看特定函数go doc fmt.Println# 查看特定类型的方法go doc net/http.ServeMux# 在浏览器中查看文档go doc-http=:6060# 然后打开 http://localhost:6060

在终端中快速查看

# 查看 fmt.Printf 的格式化动词go doc fmt.Printf# 查看 strings 包有哪些函数go doc strings|head-20# 搜索文档(Go 1.19+)go doc-allstrings|grep-i"replace"

写好自己的文档

在 Go 中,注释就是文档:

// Package calculator 提供基本的数学计算功能。packagecalculator// Add 返回两个整数的和。//// 示例://// sum := Add(1, 2)// fmt.Println(sum) // 3funcAdd(a,bint)int{returna+b}

📌 规范:文档注释以被注释的标识符名称开头,// Add ...


8. 跨平台交叉编译

Go 的一大杀器:一套代码,编译到任何平台

基本用法

GOOS(目标操作系统)和 GOARCH(目标 CPU 架构)的排列组合:

# 在 Mac 上编译 Linux 程序GOOS=linuxGOARCH=amd64 go build-ohello-linux main.go# 在 Mac 上编译 Windows 程序GOOS=windowsGOARCH=amd64 go build-ohello.exe main.go# 在 Linux 上编译 Mac 程序GOOS=darwinGOARCH=arm64 go build-ohello-mac main.go# 编译 ARM Linux(树莓派)GOOS=linuxGOARCH=arm64 go build-ohello-arm main.go

支持的平台组合

GOOSGOARCH说明
linuxamd64Linux x86-64
linuxarm64Linux ARM64(树莓派4/5)
darwinamd64macOS Intel
darwinarm64macOS Apple Silicon
windowsamd64Windows x86-64
windowsarm64Windows ARM
linuxriscv64RISC-V 架构

查看完整列表:

go tool dist list

禁用 CGO 的交叉编译

如果你的代码不依赖 C 库,建议禁用 CGO 以获得纯静态编译:

CGO_ENABLED=0GOOS=linuxGOARCH=amd64 go build-ohello-linux main.go

交叉编译脚本

把常用的编译命令写进 Makefile 或脚本:

# Makefile .PHONY: build-all build-all: GOOS=linux GOARCH=amd64 go build -o bin/hello-linux-amd64 . GOOS=linux GOARCH=arm64 go build -o bin/hello-linux-arm64 . GOOS=darwin GOARCH=amd64 go build -o bin/hello-darwin-amd64 . GOOS=darwin GOARCH=arm64 go build -o bin/hello-darwin-arm64 . GOOS=windows GOARCH=amd64 go build -o bin/hello-windows.exe . @echo "✅ 所有平台编译完成!"

9. Hello World 变体:多语言版

既然学会了 Hello World,来看看 Go 能玩出什么花样:

并发版 Hello World

packagemainimport("fmt""time")funcmain(){messages:=[]string{"Hello, World! 👋","Hola, Mundo! 🌮","Bonjour le Monde! 🥐","Ciao Mondo! 🍕","こんにちは世界! 🗾",}for_,msg:=rangemessages{gofunc(mstring){fmt.Println(m)}(msg)}// 等待 goroutine 执行完成time.Sleep(100*time.Millisecond)}

HTTP 服务器版 Hello World

packagemainimport("fmt""net/http")funcmain(){http.HandleFunc("/",func(w http.ResponseWriter,r*http.Request){fmt.Fprintf(w,"Hello, World! 🌍\n")fmt.Fprintf(w,"你访问的路径是:%s\n",r.URL.Path)})fmt.Println("服务器已启动:http://localhost:8080")http.ListenAndServe(":8080",nil)}// 运行后,打开浏览器访问 http://localhost:8080

仅仅 15 行代码,你就写出了一个 HTTP 服务器!不需要 Tomcat、不需要 Nginx、不需要任何框架。这就是 Go 标准库的强大之处。


小结与互动

📝本文要点回顾

  1. Go 程序从package main+func main()开始
  2. package声明必须在第一行,import导入依赖
  3. 三种运行方式:go run(调试)、go build(编译)、go install(安装)
  4. Go 编译为静态链接的单二进制文件,运行不需要 Go 环境
  5. go fmt强制统一代码格式,告别风格之争
  6. Go 不允许未使用的导入和变量——这是编译错误
  7. go doc离线查看文档
  8. 交叉编译一套命令搞定多平台:GOOS=linux GOARCH=amd64 go build

互动问题

  • 你的第一个 Hello World 跑起来了吗?
  • 你觉得 Go 不允许未使用的变量/导入这个设计是好是坏?
  • 试试改一下 Hello World,打印一些中文或其他内容,看看效果如何?

参考资料

  • Go 官方入门教程
  • Go 命令行文档
  • Effective Go
  • Go Build 模式

🚀下一篇:[【Go 入门到精通 2026(四):变量与数据类型】],带你掌握 Go 的类型系统,从此告别var tmp = ???的困惑!


本文由布朗克168原创发布,如需转载请联系作者并注明出处。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/18 17:34:29

Java AI 框架的两种活法:LangChain4j 狂奔,Spring AI 蓄力

一个两周发了 4 个版本,一个 RC2 之后只修 Bug 不加功能。这不是谁掉队了——是两个框架走到了不同的阶段。 LangChain4j:功能机器全速运转 打开 LangChain4j 的 Release 页面,最近一个月的版本号让人眼花: 版本时间关键词**1.1…

作者头像 李华
网站建设 2026/6/18 17:31:31

3分钟快速上手:freewrite 专注写作的终极 Mac 应用指南

3分钟快速上手:freewrite 专注写作的终极 Mac 应用指南 【免费下载链接】freewrite 项目地址: https://gitcode.com/gh_mirrors/fr/freewrite 你是否曾在写作时被各种通知、工具栏和复杂界面分散注意力?是否渴望一个纯粹、无干扰的写作环境&…

作者头像 李华
网站建设 2026/6/18 17:20:45

Django毕业设计-基于 Django+Vue 的智慧农业管理系统的设计与实现 基于 Django+Vue 的现代化农业管理平台的设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/6/18 17:20:49

MuleSoft企业级AI编排实战:打通数据孤岛与大模型的中枢架构

1. 项目概述:当企业数据孤岛撞上大模型浪潮,我们真正需要的不是更多AI,而是“AI交响指挥家”你有没有遇到过这样的场景:销售总监在晨会上拍着桌子问,“上季度EMEA大客户流失率为什么突然跳升?谁来给我一份带…

作者头像 李华
网站建设 2026/6/18 17:18:09

驰骋BPM组织结构设计技术报告

驰骋低代码 BPM 组织结构设计 — 技术报告 文档版本:2026-06 章节编号:3.1 依据代码:CCFlow/Components/BP.En30/Port(组织实体)、CCFlow/Components/BP.WF/Port/OrganizationAPI.cs(同步接口)、…

作者头像 李华
网站建设 2026/6/18 17:14:49

YTPro的贡献指南:提交PR的步骤与代码审查流程

YTPro的贡献指南:提交PR的步骤与代码审查流程 【免费下载链接】YTPro Youtube client with older Android version support, background player, Google Gemini ✨ and many more features. 项目地址: https://gitcode.com/GitHub_Trending/yt/YTPro YTPro是…

作者头像 李华