日常妙招屋
白蓝主题五 · 清爽阅读
首页  > 网络监控

Scala函数多返回值实现的小技巧

在做网络监控系统的时候,经常需要写一些工具函数来处理数据。比如从一段日志里提取出状态码和响应时间,理想情况下一个函数能同时把这两个值返回,用起来才顺手。但Scala不像某些语言直接支持多返回值,得换个思路来实现。

用元组(Tuple)最直接

最常见的方式就是让函数返回一个元组。比如写个解析日志的方法:

def parseLog(line: String): (Int, Long) = {
  val parts = line.split(" ")
  val code = parts(0).toInt
  val time = parts(1).toLong
  (code, time)
}

调用的时候可以直接解构:

val (statusCode, responseTime) = parseLog("200 150")
println(s"状态码:$statusCode,耗时:$responseTime ms")

这样一行日志的信息就轻松拆开了,写监控脚本时特别方便。

用样例类更清晰

如果返回的值多了,比如除了状态码、耗时,还要返回IP和路径,元组就容易搞混。这时候定义个样例类更靠谱:

case class LogInfo(code: Int, time: Long, ip: String, path: String)

def parseFullLog(line: String): LogInfo = {
  val parts = line.split(" ")
  LogInfo(parts(0).toInt, parts(1).toLong, parts(2), parts(3))
}

调用后可以直接用点号访问字段,代码读起来更像日常说话:

val info = parseFullLog("404 200 192.168.1.100 /api/user")
if (info.code == 404) alertUser(info.ip)

实际场景中的小应用

我们公司有个小脚本每天扫一遍访问日志,统计异常请求。以前是分开写两个函数,一个取状态码,一个取时间,调用时要重复解析字符串,效率低还容易出错。改成元组返回之后,一次解析全搞定,代码干净了不少。

有时候偷懒不想定义类,又怕元组记不清顺序,可以加个别名:

type CheckResult = (Boolean, String)

def checkServer(url: String): CheckResult = {
  // 模拟检测
  if (url.contains("down")) (false, "服务不可用")
  else (true, "正常")
}

这样别人看代码也知道返回的是“是否正常”和“提示信息”,不会搞反。

这些方法看着简单,但在写监控工具这种小而频繁的任务里,省下的功夫可不少。关键是选对场景:两三个值用元组,复杂结构上样例类,别死守一种套路就行。