Go defer的红宝石相当于什么?

rea*_*sad 7 ruby go deferred

我是Ruby的新手,我正在研究一个涉及使用它的项目.Go提供了defer声明,我想知道如何在ruby中复制该函数.

例:

dst, err := os.Create(dstName)
if err != nil {
    return
}
defer dst.Close()
Run Code Online (Sandbox Code Playgroud)

bas*_*gys 12

deferruby中的语句没有正确的等价物,但是如果要确保执行特定的代码块,则可以使用该ensure语句.不同之处在于你不能像延迟那样堆叠代码块,但结果是一样的.

在一个街区

begin
  # ...
ensure
  # This code will be executed even if an exception is thrown
end
Run Code Online (Sandbox Code Playgroud)

在一个方法

def foo
  # ...
ensure
  # ...
end
Run Code Online (Sandbox Code Playgroud)

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


Ale*_*exN 5

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

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
Run Code Online (Sandbox Code Playgroud)

示例调用:

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>'
Run Code Online (Sandbox Code Playgroud)

  • 有人对此投了反对票。为什么?这段代码不起作用吗?会产生丑陋的后果吗?这看起来合法且整洁。 (4认同)