Scala中Decline库CommandApp如何获取解析的命令行参数
核心问题澄清
你对CommandApp的执行逻辑和变量作用域理解有偏差,你留空写注释的类主体代码块,在CLI参数还没被解析的阶段就已经执行完了,根本不可能拿到运行时才会被解析出来的user参数值。
你当前写的代码里,传给
CommandApp构造函数的第三个参数main,才是程序真正的执行入口:Decline会先根据你定义的Opts规则解析用户输入的命令行参数,解析成功后才会执行mapN闭包里的逻辑,闭包内的user、quiet变量生命周期完全被限制在这个闭包内部,不存在跨作用域把变量“掏”到类主体里使用的可能。
正确的代码组织方式
你要做的POST请求逻辑,本来就应该直接写在mapN的闭包内部,完全不需要跑到类的空块里取参数。
最小修改可运行示例
import cats.implicits._ import com.monovore.decline._ // 在这里导入你发POST请求需要的客户端依赖即可 object Main extends CommandApp( name = "hello-world", header = "Says hello!", main = { // 这部分仅声明参数解析规则,不代表已经拿到参数值 val userOpt = Opts.option[String]("target", help = "Person to greet.").withDefault("world") val quietOpt = Opts.flag("quiet", help = "Whether to be quiet.").orFalse // mapN闭包内:已经拿到解析完成的真实参数,在这里写全部业务逻辑 (userOpt, quietOpt).mapN { (user, quiet) => if (quiet) { println("...") } else { println(s"Hello $user!") // 直接在这里写POST请求逻辑就行,不需要外取变量 // 例如:httpClient.post("/greet", body = s"hello $user") } } } )
如果代码量太大想拆分模块
不要硬把变量拽到类作用域里,把业务逻辑抽成独立函数,把解析出来的参数当入参传进去就行:
- 先把独立的业务逻辑抽成方法,需要什么参数就定义什么入参:
// 独立的POST请求逻辑,和CLI解析完全解耦 def sendGreetRequest(targetUser: String, enableQuietMode: Boolean): Unit = { if (enableQuietMode) return // 写实际的POST请求实现 println(s"已向 $targetUser 发送问候请求") }
- 再在
mapN闭包里把解析好的参数传给这个方法:
(userOpt, quietOpt).mapN { (user, quiet) => sendGreetRequest(user, quiet) }
常见误区提醒
- 不要在类主体的大括号块里写依赖CLI参数的逻辑:这个块的执行时机是Main对象初始化阶段,此时命令行参数还没经过Decline解析,就算你想硬取也拿不到值
- Decline的参数设计是纯函数式的,没有把解析后的参数存成类成员变量的设计,所有拿到参数后的业务逻辑,天然就应该和参数解析的闭包绑定
内容的提问来源于stack exchange,提问作者Ry2254
相关产品推荐
相关产品推荐

