ZetCode

Ruby BEGIN 和 END 关键字

最后修改日期:2025 年 4 月 27 日

本教程解释了如何使用 Ruby 的 BEGINEND 关键字。这些特殊块控制代码在程序开始和退出时的执行。

BEGIN 关键字定义了一个在任何其他代码运行之前运行的块。END 关键字定义了一个在所有其他代码运行之后运行的块。

这些钩子对于初始化和清理任务很有用。它们会执行,而不管程序流程或退出条件如何。多个块按顺序堆叠。

基本的 BEGIN 和 END 示例

这个简单的例子演示了 BEGIN 和 END 块的执行顺序。请注意,它们在正常程序流程之外运行。

basic_begin_end.rb
BEGIN {
  puts "This runs first"
}

END {
  puts "This runs last"
}

puts "This runs in between"

BEGIN 块在任何其他代码之前执行,而 END 在所有代码之后运行。主程序输出按预期出现在它们之间。

多个 BEGIN/END 块

Ruby 允许有多个 BEGINEND 块。BEGIN 块按定义顺序运行,而 END 块按相反顺序执行(像堆栈一样)。

multiple_blocks.rb
BEGIN {
  puts "BEGIN 1"
}

BEGIN {
  puts "BEGIN 2"
}

END {
  puts "END 1"
}

END {
  puts "END 2"
}

puts "Main program"

请注意,BEGIN 块从上到下执行,而 END 块从下到上执行。这种行为在所有 Ruby 版本中都是一致的。

BEGIN 结合变量初始化

BEGIN 块可以初始化主程序中使用的变量。此示例在主代码运行之前进行配置。

initialization.rb
BEGIN {
  $app_name = "My Ruby Program"
  $start_time = Time.now
}

puts "Welcome to #{$app_name}"
puts "Started at #{$start_time}"

END {
  puts "Program ran for #{Time.now - $start_time} seconds"
}

全局变量($)最好,因为它们避免了作用域问题。END 块使用 BEGIN 初始化的时间来计算总运行时间。

END 块中的错误处理

即使程序提前退出或引发异常,END 块也会执行。这使它们成为清理任务的理想选择。

error_handling.rb
BEGIN {
  puts "Starting risky operation"
}

END {
  puts "Cleanup always happens"
}

raise "Something went wrong!" if rand < 0.5

puts "This might not run"

无论程序成功完成还是失败,END 块都会运行。这确保了资源得到妥善释放,无论结果如何。

使用 BEGIN/END 进行文件操作

一个常见的用例是文件处理——在 BEGIN 中打开,在 END 中关闭。这确保了正确的资源管理。

file_operations.rb
BEGIN {
  $log_file = File.open("output.log", "w")
  $log_file.puts "Log started: #{Time.now}"
}

def log(message)
  $log_file.puts message
end

log("Processing started")

END {
  $log_file.puts "Log ended: #{Time.now}"
  $log_file.close
  puts "Log file closed"
}

log("Processing completed")

文件在任何日志记录发生之前打开,并在所有操作完成后关闭。这种模式可确保没有资源泄漏。

BEGIN 结合命令行参数

BEGIN 块可以在主程序之前处理 ARGV。本例处理早期参数解析。

argv_processing.rb
BEGIN {
  $verbose = ARGV.delete("--verbose")
  puts "Verbose mode enabled" if $verbose
}

puts "Remaining arguments: #{ARGV.inspect}"

END {
  puts "Verbose logging complete" if $verbose
}

BEGIN 块在主程序看到 ARGV 之前修改它。如果启用了详细操作,END 块可以报告。

复杂的程序结构

本示例展示了在具有多个组件的更大程序中的 BEGIN/END。这些块有助于组织设置和拆卸。

program_structure.rb
BEGIN {
  require 'json'
  require 'net/http'
  $config = JSON.parse(File.read('config.json'))
}

BEGIN {
  $stats = {
    start: Time.now,
    requests: 0
  }
}

def make_request(url)
  $stats[:requests] += 1
  Net::HTTP.get(URI(url))
end

make_request($config['api_endpoint'])

END {
  duration = Time.now - $stats[:start]
  puts "Made #{$stats[:requests]} requests in #{duration} seconds"
  File.write('stats.json', JSON.dump($stats))
}

BEGIN 块加载依赖项并初始化跟踪。END 块无论程序如何终止都会保存统计信息。

来源

Ruby 关键字文档

本教程涵盖了 Ruby 的 BEGIN 和 END 块,并附有实际示例,展示了初始化、清理和错误处理模式。

作者

我叫 Jan Bodnar,我是一名充满激情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1400 多篇文章和 8 本电子书。我在教授编程方面有十多年的经验。

列出 所有 Ruby 教程