# Using Go packages


Until Xo has its own ecosystem, any Go package is one line away:

`gointerop/main.xo`

```xo
use go "strings"
use go "net/url"

fn main(os: Os) ! {
  os.stdio.println(strings.to_upper("hello from go"))
  let u = url.parse("https://xolang.dev/docs?tab=tour")?
  os.stdio.println("${u.hostname()} ${u.query().get("tab")}")
}
```

Output:

```text
HELLO FROM GO
xolang.dev tour
```



- `xo check`, `build`, `run`, and `test` generate the bindings themselves.
- Names follow Xo's style: `ToUpper` is `to_upper`.
- Go's `(T, error)` becomes `T ! go.Error`, so `url.parse(...)?` works like
  any Xo call, and a pointer that may be nil becomes `T?`.
- Every call into Go performs the `go` effect. Go code can reach files and
  the network without a capability, so a `pub` function that calls Go must
  say `uses go`, and that escape stays visible in signatures.

Native builds can call C the same way with `use c "header.h"`; see section
4.5 of the [specification](../../spec/core/#45-c-headers-p2-native-builds).

That is the tour. The [specification](../../spec/core/) covers everything in
full, and the [diagnostics reference](../../diagnostics/) explains every
error code.

