I/O
Command-Line Arguments and Flags
How Node.js's process.argv/util.parseArgs compares to os.Args/flag (Go), env::args (Rust), CommandLine (Swift), and main's parameter (Java).
- Minimum versions
- Node.js ≥ 18.11Go ≥ 1.0Rust ≥ 1.85Swift ≥ 4.0Java ≥ 25
- Verified on
- Node.js 24.12.0Go 1.27.1Rust 1.98.1Swift 6.2.4Java 25.0.4.1
Node.js code is an ES module: save it as .mjs or set "type": "module" in package.json.
There are two ways to get input from the command line: read the raw argument array directly, or parse it into named flags (--foo=bar). Node.js and Go ship both options in their standard library. Rust's std only has env::args() (raw arguments) — named flags need the clap crate. Swift and Java have no flag-parsing package in their standard library/Foundation at all; the examples below parse --foo=/--qux by hand, while real projects typically reach for the swift-argument-parser package (Swift, via Swift Package Manager) or picocli (Java) for that.
Raw command-line arguments
const args = process.argv.slice(2)
console.log(args)package main
import (
"fmt"
"os"
)
func main() {
args := os.Args[1:]
fmt.Println(args)
}use std::env;
fn main() {
let args: Vec<String> = env::args().skip(1).collect(); // args().next() is the binary's own path
println!("{args:?}");
}let args = CommandLine.arguments.dropFirst() // arguments[0] is the binary's own path
print(Array(args))void main(String[] args) { // args here already excludes the program's own path
IO.println(Arrays.toString(args));
}$ node cli_args.js foo bar qux
[ 'foo', 'bar', 'qux' ]
$ go run cli_args.go foo bar qux
[foo bar qux]
$ cargo run -- foo bar qux
["foo", "bar", "qux"]
$ swift cli_args.swift foo bar qux
["foo", "bar", "qux"]
$ java Main.java foo bar qux
[foo, bar, qux]Named command-line flags
import { parseArgs } from 'node:util'
const { values: { foo, qux } } = parseArgs({
options: {
foo: { type: 'string', default: 'default value' },
qux: { type: 'boolean', default: false }
}
})
console.log('foo:', foo)
console.log('qux:', qux)package main
import (
"flag"
"fmt"
)
func main() {
var foo string
flag.StringVar(&foo, "foo", "default value", "a string var")
var qux bool
flag.BoolVar(&qux, "qux", false, "a bool var")
flag.Parse()
fmt.Println("foo:", foo)
fmt.Println("qux:", qux)
}// Cargo.toml: clap = { version = "4", features = ["derive"] }
use clap::Parser;
#[derive(Parser)]
struct Args {
#[arg(long, default_value = "default value")]
foo: String,
#[arg(long, default_value_t = false)] // a bool field automatically becomes a bare flag (--qux, no value)
qux: bool,
}
fn main() {
let args = Args::parse();
println!("foo: {}", args.foo);
println!("qux: {}", args.qux);
}// Swift's standard library has no flag-parsing package; parsed by hand for this short example.
// Real projects should reach for the swift-argument-parser package (@main + ParsableCommand) via SwiftPM.
var foo = "default value"
var qux = false
for arg in CommandLine.arguments.dropFirst() {
if arg == "--qux" {
qux = true
} else if arg.hasPrefix("--foo=") {
foo = String(arg.dropFirst("--foo=".count))
}
}
print("foo: \(foo)")
print("qux: \(qux)")void main(String[] args) { // java.base has no flag-parsing package; parsed by hand for this short example
String foo = "default value";
boolean qux = false;
for (String arg : args) {
if (arg.equals("--qux")) {
qux = true;
} else if (arg.startsWith("--foo=")) {
foo = arg.substring("--foo=".length());
}
}
IO.println("foo: " + foo);
IO.println("qux: " + qux);
}$ node cli_flags.js --foo='bar' --qux
foo: bar
qux: true
$ go run cli_flags.go -foo='bar' -qux=true
foo: bar
qux: true
$ cargo run -- --foo=bar --qux
foo: bar
qux: true
$ swift cli_flags.swift --foo=bar --qux
foo: bar
qux: true
$ java Main.java --foo=bar --qux
foo: bar
qux: trueKey differences
| Node.js | Go | Rust | Swift | Java | |
|---|---|---|---|---|---|
| Raw arguments | process.argv.slice(2) |
os.Args[1:] |
env::args() |
CommandLine.arguments |
main's args parameter |
| Parsing named flags | util.parseArgs() |
the flag package |
the clap crate |
not built in | not built in |
| Flag prefix | --foo |
-foo (one or two dashes both work) |
--foo |
up to your own parsing | up to your own parsing |
| Boolean flags | --qux (takes no value) |
-qux or -qux=true (never -qux true) |
--qux (takes no value) |
up to your own parsing | up to your own parsing |
Reference: github.com/miguelmota/golang-for-nodejs-developers#cli-args