如何在ZIO中执行try and catch?

Bla*_*man 1 io scala zio

我使用 ZIO 的第一步,我尝试使用兼容的 ZIO 版本转换此 readfile 函数。

下面的代码片段可以编译,但我不会关闭 ZIO 版本中的源代码。我怎么做?

 def run(args: List[String]) =
    myAppLogic.exitCode

  val myAppLogic =
    for {
      _    <- readFileZio("C:\\path\\to\file.csv")
      _    <- putStrLn("Hello! What is your name?")
      name <- getStrLn
      _    <- putStrLn(s"Hello, ${name}, welcome to ZIO!")
    } yield ()

  def readfile(file: String): String = {
    val source = scala.io.Source.fromFile(file)
    try source.getLines.mkString finally source.close()
  }

  def readFileZio(file: String): zio.Task[String] = {
    val source = scala.io.Source.fromFile(file)
    ZIO.fromTry[String]{
      Try{source.getLines.mkString}
    }
    
  }
Run Code Online (Sandbox Code Playgroud)

Krz*_*sik 5

解决您的问题的最简单的解决方案是使用bracket函数,其本质上与try-finally块具有类似的目的。它作为关闭资源(在您的情况下Source)的第一个参数效果和使用它的第二个效果。

所以你可以重写readFileZio 如下:

def readFileZio(file: String): Task[Iterator[String]] =
  ZIO(Source.fromFile(file))
    .bracket(
      s => URIO(s.close),
      s => ZIO(s.getLines())
  )
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用ZManagedwhich 是一种封装打开和关闭资源操作的数据类型:

def managedSource(file: String): ZManaged[Any, Throwable, BufferedSource] = 
   Managed.make(ZIO(Source.fromFile(file)))(s => URIO(s.close))
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

def readFileZioManaged(file: String): Task[Iterator[String]] =
    managedSource(file).use(s => ZIO(s.getLines()))
Run Code Online (Sandbox Code Playgroud)