Gleam 语言入门¶
为什么要学¶
Gleam 是运行在 Erlang VM (BEAM) 上的类型安全函数式语言,结合了 Erlang 的并发能力和现代语言的开发体验:
- 类型安全:静态类型+类型推断,编译时捕获错误
- BEAM 并发:继承 Erlang/Elixir 的 Actor 模型和容错能力
- 友好语法:类似 Rust/Swift 的现代语法,非 Erlang 的怪异语法
- 互操作:可以调用 Erlang/Elixir 生态的所有库
- JS 编译:同一份代码可以编译为 JavaScript 运行在浏览器/Node
- 零运行时错误:类型系统设计目标是消除运行时异常
如果你想用 Erlang VM 的强大并发能力但不想学 Erlang 的语法,Gleam 是完美的桥梁。
核心概念¶
白话解释¶
- BEAM VM:Erlang 的虚拟机,以高并发和容错闻名(WhatsApp 就用这个)
- 不可变数据:数据一旦创建就不能修改,要改就创建新的
- 模式匹配:像"拆包裹"一样检查和解构数据
- Result 类型:用 Ok/Error 表示操作结果,不用异常机制
- 管道运算符:
|>把前一步的结果传给下一步,代码像读句子
核心概念对照表¶
| 概念 | Gleam | 其他语言类比 |
|---|---|---|
| 类型推断 | 自动推断,可省略注解 | TypeScript/Rust |
| 模式匹配 | case expression | Rust match |
| 管道 | \|> 运算符 | Unix管道 \| |
| Result | Ok(value) / Error(e) | Rust Result |
| Option | Some(v) / None | Rust Option |
| Module | 文件即模块 | Python/Elixir |
| OTP | 进程/消息/监督树 | Erlang Actor |
| Use | 类似do-notation | 简化回调嵌套 |
安装配置¶
安装¶
# macOS
brew install gleam erlang rebar3
# Linux (预编译)
curl -fsSL https://gleam.run/install.sh | sh
# 确保Erlang已安装
# Ubuntu
sudo apt install erlang
# 验证
gleam --version
创建项目¶
gleam new my_app
cd my_app
# 项目结构:
# ├── gleam.toml
# ├── src/
# │ └── my_app.gleam
# └── test/
# └── my_app_test.gleam
gleam.toml¶
name = "my_app"
version = "1.0.0"
target = "erlang" # 或 "javascript"
[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
gleam_erlang = ">= 0.25.0 and < 1.0.0"
[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
快速上手¶
基础语法¶
// src/my_app.gleam
import gleam/io
import gleam/int
import gleam/string
pub fn main() {
// 变量绑定(不可变)
let name = "Gleam"
let age = 3
// 字符串拼接
let greeting = "Hello, " <> name <> "!"
io.println(greeting)
// 整数转字符串
io.println("Age: " <> int.to_string(age))
// 管道运算符
"hello world"
|> string.uppercase
|> string.reverse
|> io.println
}
类型和函数¶
import gleam/float
import gleam/int
// 自定义类型(类似enum)
pub type Shape {
Circle(radius: Float)
Rectangle(width: Float, height: Float)
Triangle(base: Float, height: Float)
}
// 函数+模式匹配
pub fn area(shape: Shape) -> Float {
case shape {
Circle(r) -> float.pi *. r *. r
Rectangle(w, h) -> w *. h
Triangle(b, h) -> 0.5 *. b *. h
}
}
// 泛型函数
pub fn first(list: List(a)) -> Result(a, Nil) {
case list {
[head, ..] -> Ok(head)
[] -> Error(Nil)
}
}
管道和链式处理¶
import gleam/list
import gleam/int
import gleam/string
pub fn process_numbers() -> String {
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|> list.filter(fn(x) { x > 3 })
|> list.map(fn(x) { x * 2 })
|> list.fold(0, int.add)
|> int.to_string
|> string.append(" is the result")
}
Result 错误处理¶
import gleam/int
import gleam/result
pub type AppError {
ParseError(String)
NotFound
Unauthorized
}
pub fn parse_age(input: String) -> Result(Int, AppError) {
input
|> int.parse
|> result.map_error(fn(_) { ParseError("无法解析年龄: " <> input) })
}
pub fn validate_age(age: Int) -> Result(Int, AppError) {
case age {
a if a >= 0 && a <= 150 -> Ok(a)
_ -> Error(ParseError("年龄不合法"))
}
}
// 使用use简化Result链
pub fn process_input(input: String) -> Result(String, AppError) {
use age <- result.try(parse_age(input))
use valid_age <- result.try(validate_age(age))
Ok("年龄: " <> int.to_string(valid_age))
}
进阶用法¶
1. OTP 并发(Actor)¶
import gleam/erlang/process.{type Subject}
import gleam/otp/actor
// 定义消息类型
pub type Message {
Increment
Decrement
GetCount(reply_to: Subject(Int))
}
// Actor状态
pub type State = Int
// 创建counter actor
pub fn start_counter() -> Result(Subject(Message), actor.StartError) {
actor.start(0, fn(message: Message, state: State) -> actor.Next(Message, State) {
case message {
Increment -> actor.continue(state + 1)
Decrement -> actor.continue(state - 1)
GetCount(reply_to) -> {
process.send(reply_to, state)
actor.continue(state)
}
}
})
}
// 使用
pub fn main() {
let assert Ok(counter) = start_counter()
process.send(counter, Increment)
process.send(counter, Increment)
process.send(counter, Increment)
let count = process.call(counter, GetCount, 1000)
// count = 3
}
2. Web 开发(Wisp框架)¶
import gleam/http/request.{type Request}
import gleam/http/response.{type Response}
import wisp.{type Request as WispRequest}
import mist
pub fn main() {
let assert Ok(_) =
wisp.mist_handler(handle_request, "secret")
|> mist.new
|> mist.port(8000)
|> mist.start_http
process.sleep_forever()
}
fn handle_request(req: WispRequest) -> Response(wisp.Body) {
case wisp.path_segments(req) {
[] -> wisp.ok() |> wisp.string_body("Hello Gleam!")
["api", "users"] -> handle_users(req)
_ -> wisp.not_found()
}
}
fn handle_users(req: WispRequest) -> Response(wisp.Body) {
case req.method {
http.Get -> {
let json = "[{\"name\": \"张三\"}]"
wisp.ok()
|> wisp.set_header("content-type", "application/json")
|> wisp.string_body(json)
}
_ -> wisp.method_not_allowed([http.Get])
}
}
3. JSON 处理¶
import gleam/json
import gleam/dynamic
pub type User {
User(name: String, age: Int, email: String)
}
// 编码
pub fn encode_user(user: User) -> String {
json.object([
#("name", json.string(user.name)),
#("age", json.int(user.age)),
#("email", json.string(user.email)),
])
|> json.to_string
}
// 解码
pub fn decode_user(json_string: String) -> Result(User, json.DecodeError) {
let decoder = dynamic.decode3(
User,
dynamic.field("name", dynamic.string),
dynamic.field("age", dynamic.int),
dynamic.field("email", dynamic.string),
)
json.decode(from: json_string, using: decoder)
}
4. 编译到 JavaScript¶
5. 测试¶
// test/my_app_test.gleam
import gleeunit
import gleeunit/should
import my_app
pub fn main() {
gleeunit.main()
}
pub fn area_circle_test() {
my_app.area(my_app.Circle(1.0))
|> should.equal(3.141592653589793)
}
pub fn parse_age_valid_test() {
my_app.parse_age("25")
|> should.equal(Ok(25))
}
pub fn parse_age_invalid_test() {
my_app.parse_age("abc")
|> should.be_error
}
常见问题¶
Q1: Gleam vs Elixir?¶
| 方面 | Gleam | Elixir |
|---|---|---|
| 类型系统 | 静态类型 | 动态类型 |
| 语法 | 类C/Rust | 类Ruby |
| 错误处理 | Result类型 | 异常+模式匹配 |
| 生态 | 小但增长 | 成熟丰富 |
| 互操作 | 可调用Erlang/Elixir | 可调用Erlang |
| 适合 | 想要类型安全 | 想要灵活性 |
Q2: 性能如何?¶
运行在 BEAM VM 上,性能与 Erlang/Elixir 相当。适合 I/O 密集型和高并发场景,不适合纯 CPU 计算密集型任务。
Q3: 生态足够吗?¶
Gleam 自己的包还在增长中,但可以直接使用整个 Erlang/Elixir 生态(通过 FFI),所以实际可用的库非常多。
Q4: 适合什么场景?¶
- 高并发 Web 服务
- 实时系统(聊天、游戏服务器)
- 分布式系统
- 需要高可用性的后端服务
参考资源¶
- Gleam 官网 - 官方网站
- Gleam 教程 - 交互式教程
- Gleam GitHub - 源代码
- Gleam 包管理 - 包注册表
- Gleam Discord - 社区