Nim 完全指南 / 03 第一个程序
第 03 章:第一个程序
3.1 最简单的 Nim 程序
创建文件 hello.nim:
# hello.nim
echo "Hello, World!"
编译并运行:
nim c -r hello.nim
输出:
Hello, World!
这就是 Nim 的全部——一行代码,一个完整的程序。没有 main 函数,没有类,没有命名空间声明。
编译过程详解
nim c hello.nim # 仅编译,生成 hello(Linux)或 hello.exe(Windows)
nim c -r hello.nim # 编译并运行
nim c -o:myapp hello.nim # 指定输出文件名
编译步骤:
hello.nim → [Nim 编译器] → hello.c → [GCC/Clang] → hello(可执行文件)
3.2 基本输出
echo 函数
echo 是 Nim 中最常用的输出函数:
# 输出字符串
echo "Hello, Nim!"
# 输出数字
echo 42
echo 3.14
# 输出多个值(用逗号分隔)
echo "Name: ", "Nim", ", Version: ", NimVersion
# 输出表达式
echo "2 + 3 = ", 2 + 3
# 输出序列
echo @[1, 2, 3, 4, 5]
格式化输出
# 方法一:字符串拼接
let name = "Nim"
let version = 2
echo "Welcome to " & name & " " & $version & "!"
# 方法二:使用 & 格式化字符串(需要 import std/strformat)
import std/strformat
let pi = 3.14159
echo &"Pi is approximately {pi:.2f}"
# 输出: Pi is approximately 3.14
let items = 5
let price = 9.99
echo &"Total: {items} × ${price:.2f} = ${items.float * price:.2f}"
# 输出: Total: 5 × $9.99 = $49.95
write 和 writeLine
# write 不换行,echo 换行
stdout.write "Hello, "
stdout.write "World!"
stdout.write "\n"
# writeLine 等同于 echo
stdout.writeLine "This is a line"
3.3 基本输入
# 读取一行输入
echo "What is your name?"
let name = stdin.readLine()
echo "Hello, ", name, "!"
# 读取整数
echo "Enter a number:"
let num = parseInt(stdin.readLine())
echo "You entered: ", num
# 读取多个值
echo "Enter two numbers (space separated):"
let parts = stdin.readLine().split(" ")
let a = parseInt(parts[0])
let b = parseInt(parts[1])
echo &"{a} + {b} = {a + b}"
3.4 NimScript
Nim 支持 .nims 脚本文件,无需编译即可运行:
# 直接运行脚本
nim e hello.nims
# 或者给脚本添加执行权限
chmod +x hello.nims
./hello.nims
hello.nims:
#!/usr/bin/env nim e
echo "Running as NimScript!"
echo "Nim version: ", NimVersion
echo "Current OS: ", hostOS
NimScript 与编译模式的区别:
| 特性 | 编译模式 (nim c) | 脚本模式 (nim e) |
|---|---|---|
| 运行速度 | 极快(原生代码) | 较慢(解释执行) |
| 系统调用 | 完整支持 | 有限制 |
| FFI | 完整支持 | 不支持 |
importc | 完整支持 | 不支持 |
| 适用场景 | 应用开发 | 构建脚本、配置 |
3.5 项目结构
3.5.1 标准项目布局
myproject/
├── src/ # 源代码目录
│ ├── myproject.nim # 入口文件
│ ├── myproject/ # 模块目录
│ │ ├── utils.nim
│ │ ├── models.nim
│ │ └── config.nim
│ └── myprojectpkg/ # 包模块目录
│ └── private.nim
├── tests/ # 测试目录
│ ├── test_utils.nim
│ └── test_models.nim
├── docs/ # 文档目录
├── bin/ # 编译输出目录
├── nimcache/ # 编译缓存(不应提交到版本控制)
├── config.nims # 项目配置
├── myproject.nimble # 包配置
├── .gitignore
└── README.md
3.5.2 nimble init 生成的项目
nimble init myproject
这会创建:
myproject/
├── src/
│ └── myproject.nim # 入口
├── tests/
│ └── test1.nim # 测试
└── myproject.nimble # 包描述
默认入口文件 src/myproject.nim:
# This is just an example to get you started. A typical library package
# exports the main API in this file. Note that you cannot rename this file
# but you can remove it if you wish.
proc add*(x, y: int): int =
## Adds two numbers together.
return x + y
when isMainModule:
echo add(2, 3)
3.5.3 命名约定
| 组件 | 约定 | 示例 |
|---|---|---|
| 源文件 | 小写下划线 | my_module.nim |
| 模块目录 | 小写下划线 | my_module/ |
| 包名 | 小写 | myproject |
| 入口文件 | 与项目同名 | myproject.nim |
| 测试文件 | test_ 前缀 | test_utils.nim |
3.6 编译模式详解
3.6.1 Debug 模式(默认)
nim c main.nim
# 等同于
nim c --assertions:on --checks:on --hints:on main.nim
特点:
- 启用所有运行时检查
- 包含调试信息
- 未启用优化
- 适合开发调试
3.6.2 Release 模式
nim c -d:release main.nim
特点:
- 启用编译器优化
- 关闭运行时检查
- 生成更小的二进制文件
- 适合生产部署
3.6.3 Danger 模式
nim c -d:danger main.nim
特点:
- 关闭所有安全检查
- 最大优化
- 可能导致未定义行为
- 仅用于性能基准测试
3.6.4 对比表
| 特性 | Debug | Release | Danger |
|---|---|---|---|
| 运行时检查 | ✅ | ❌ | ❌ |
| 数组边界检查 | ✅ | ❌ | ❌ |
| 优化级别 | O0 | O3 | O3 |
| 调试信息 | ✅ | ❌ | ❌ |
| 二进制大小 | 大 | 中 | 小 |
| 运行速度 | 慢 | 快 | 最快 |
| 适用场景 | 开发调试 | 生产部署 | 性能测试 |
3.7 条件编译
when 语句
# 根据操作系统选择不同行为
when defined(windows):
echo "Running on Windows"
elif defined(linux):
echo "Running on Linux"
elif defined(macosx):
echo "Running on macOS"
else:
echo "Unknown OS"
# 根据编译模式
when defined(release):
echo "Release build"
else:
echo "Debug build"
# 根据编译后端
when defined(js):
proc alert(msg: string) {.importjs: "alert(#)".}
alert("In JavaScript!")
else:
echo "In native code!"
自定义编译标志
# 使用 -d 标志定义自定义符号
# 编译: nim c -d:verbose -d:version=2 main.nim
when defined(verbose):
echo "Verbose mode enabled"
const Version {.intdefine.} = 1
echo "Version: ", Version
定义常量
# 在命令行定义
# nim c -d:appName=MyApp main.nim
const appName {.strdefine.} = "DefaultApp"
echo "Running: ", appName
3.8 多文件项目示例
创建项目
mkdir -p myapp/src/myapp
cd myapp
nimble init myapp -y
src/myapp.nim(入口)
# src/myapp.nim
import myapp/[calculator, formatter]
when isMainModule:
let result = add(10, 20)
echo formatResult("Addition", 10, 20, result)
let product = multiply(5, 6)
echo formatResult("Multiplication", 5, 6, product)
src/myapp/calculator.nim
# src/myapp/calculator.nim
proc add*(a, b: int): int =
## Add two integers
return a + b
proc subtract*(a, b: int): int =
## Subtract b from a
return a - b
proc multiply*(a, b: int): int =
## Multiply two integers
return a * b
proc divide*(a, b: float): float =
## Divide a by b
if b == 0:
raise newException(DivByZeroDefect, "Cannot divide by zero")
return a / b
src/myapp/formatter.nim
# src/myapp/formatter.nim
import std/strformat
proc formatResult*(op: string, a, b, result: int): string =
## Format a calculation result as a string
&"{op}: {a} and {b} = {result}"
proc formatCurrency*(amount: float, currency: string = "$"): string =
## Format a number as currency
&"{currency}{amount:.2f}"
编译运行
nim c -r src/myapp.nim
输出:
Addition: 10 and 20 = 30
Multiplication: 5 and 6 = 30
3.9 注释与文档
# 这是单行注释
#[这是
多行
注释]#
proc add*(a, b: int): int =
## 计算两个整数的和
##
## .. code-block:: nim
## echo add(1, 2) # 输出 3
return a + b
type
User* = object
## 用户对象
##
## 存储用户的基本信息
name*: string ## 用户名
age*: int ## 年龄
生成文档:
nim doc src/myapp.nim
# 生成 src/myapp.html
3.10 实用开发技巧
快速测试代码片段
# 使用 -e 标志直接执行代码
nim e -e "echo 2 + 2"
# 使用 --eval 标志
nim --eval:"echo \"Hello\""
查看编译器输出的 C 代码
# 查看生成的 C 代码
nim c --genScript main.nim
cat nimcache/main.c
交叉编译
# 为 Linux ARM64 编译
nim c --os:linux --cpu:arm64 main.nim
# 为 Windows 编译
nim c --os:windows --cpu:amd64 main.nim
本章小结
| 要点 | 内容 |
|---|---|
| 编译命令 | nim c -r file.nim |
| 输出函数 | echo、stdout.write |
| 输入函数 | stdin.readLine() |
| 格式化 | strformat 模块的 &"{}" 语法 |
| 脚本模式 | nim e file.nims |
| 项目结构 | src/(源码)、tests/(测试)、bin/(输出) |
| 编译模式 | Debug(默认)、Release(-d:release)、Danger(-d:danger) |
练习
- 编写一个程序,读取用户输入的姓名和年龄,格式化输出问候语
- 创建一个多文件项目,包含一个工具模块和一个主入口
- 分别使用 Debug 和 Release 模式编译,比较二进制文件大小
- 编写一个 NimScript 文件,列出当前目录的所有
.nim文件
扩展阅读
← 上一章:安装与环境配置 | 下一章:变量与类型 →