什么是Ruby的Go defer等价物?

gojuced7  于 2023-09-28  发布在  Go
关注(0)|答案(2)|浏览(122)

我是一个新的Ruby,我正在做一个项目,其中涉及使用这个。Go提供了defer语句,我想知道如何在Ruby中复制该函数。
范例:

dst, err := os.Create(dstName)
if err != nil {
    return
}
defer dst.Close()
r8xiu3jd

r8xiu3jd1#

在ruby中没有与defer语句等价的语句,但是如果你想确保特定的代码块被执行,你可以使用ensure语句。不同之处在于,您不能像defer那样堆叠代码块,但结果是相同的。

一个街区

begin
  # ...
ensure
  # This code will be executed even if an exception is thrown
end

方法中

def foo
  # ...
ensure
  # ...
end

Object#ensure标记开始/结束块的最后一个可选子句,通常在块还包含rescue子句的情况下。确保子句中的代码被保证执行,无论控制是否流向救援块。

ddhy6vgd

ddhy6vgd2#

它没有这样的语句,但是您可以使用元编程来获得这种行为。

module Deferable
  def defer &block
    @defered_methods << block
  end

  def self.included(mod)
    mod.extend ClassMethods
  end

  module ClassMethods
    def deferable method
      original_method = instance_method(method)
      define_method(method) do |*args|
        @@defered_method_stack ||= []
        @@defered_method_stack << @defered_methods
        @defered_methods = []
        begin
          original_method.bind(self).(*args)
        ensure
          @defered_methods.each {|m| m.call }
          @defered_methods = @@defered_method_stack.pop
        end
      end
    end
  end
end

class Test
  include Deferable

  def test
    defer { puts "world" }
    puts "hello"
  end

  def stacked_methods str
    defer { puts "and not broken" }
    defer { puts "at all" }
    puts str
    test
  end

  def throw_exception
    defer { puts "will be executed even if exception is thrown" }
    throw Exception.new
  end

  deferable :test
  deferable :stacked_methods
  deferable :throw_exception
end

示例调用:

t = Test.new
t.test

# -> Output:
# hello
# world

t.stacked_methods "stacked methods"

# -> Output:
# stacked methods
# hello
# world
# and not broken
# at all

t.throw_exception
# -> Output:
# will be executed even if exception is thrown
# deferable.rb:45:in `throw': uncaught throw #<Exception: Exception> (UncaughtThrowError)
#         from deferable.rb:45:in `throw_exception'
#         from deferable.rb:18:in `call'
#         from deferable.rb:18:in `block in deferable'
#         from deferable.rb:59:in `<main>'

相关问题