An open API service indexing awesome lists of open source software.

https://github.com/aisk/mygo

なんで……なんで「?」演算子、入れたの!?
https://github.com/aisk/mygo

go

Last synced: 1 day ago
JSON representation

なんで……なんで「?」演算子、入れたの!?

Awesome Lists containing this project

README

          

# mygo

![logo](https://github.com/user-attachments/assets/7867a592-fe16-4997-bc95-f634e453a0c7)

mygo is an experimental *toy* Go preprocessor/transpiler that adds a `?` operator for concise error handling.

For example, `mygo` transforms this:

```go
s := hello()?
```

into standard Go:

```go
s, err := hello()
if err != nil {
return err
}
```

You can also provide a custom error handler block after `?`:

```go
s := hello()? {
return fmt.Errorf("hello failed: %w", err)
}
```

which becomes:

```go
s, err := hello()
if err != nil {
return fmt.Errorf("hello failed: %w", err)
}
```

## Installation

```sh
$ go install github.com/aisk/mygo@latest
```

## Usage

Create `hello.mygo`:

```go
package main

import (
"io"
"os"
)

func hello() error {
f := os.Open("hello.mygo")?
defer f.Close()
s := io.ReadAll(f)?
println(string(s))
return nil
}

func main() {
hello()
}
```

`mygo` supports multiple ways to specify transpile targets:

```sh
$ cat hello.mygo | mygo > hello.go
$ mygo hello.mygo
$ mygo .
$ mygo ./...
$ mygo ...
```

### Integrating with `go generate`

You can keep `.mygo` files as the editable source and generate `.go` files before normal Go builds:

```go
// generate.go
package main

//go:generate mygo hello.mygo
```

Then run:

```sh
$ go generate ./...
$ go test ./...
```

For multiple files or packages, point the directive at a directory:

```go
//go:generate mygo .
//go:generate mygo ./...
```

## Why

mygo tries to add syntax sugar without adding runtime lock-in. The generated files are plain Go code:

- no runtime dependency
- no special library
- no custom Go compiler

## Constraints

To keep the generated Go readable, mygo intentionally avoids some rewrites:

- method chaining like `a()?.b()?` is not supported
- `?` in `for` initialization statements is not supported yet
- expression statements like `f()?` require `f` to return only `error`; use `_ = f()?` when discarding non-error return values
- custom handlers use the generated `err` variable and must return or otherwise handle control flow themselves