1
0

教育用のGo言語?Go+を触ってみた

Posted at

TL; DR

  • Goの構文をよりスクリプト言語っぽく手軽に
  • Goの標準パッケージが利用可能
  • シェルとして使用可能

はじめに

GitHubのプログラミング言語タグを見ていたところ、Go+ という言語を見つけました。

READMEによると「エンジニアリング」「理工系の教育」「データサイエンス」向けを謳っているようです。
名前の通りGo言語互換で、さらに + となるいくつかの機能が追加されていました(JavaScriptに対するTypeScript的なイメージ)。
本記事では、Go+で面白いと思った構文について紹介したいと思います。

バージョン

  • Go+: v1.1.8 (執筆時点の最新)

実行方法

まずは公式のガイドに従い gop をインストールします。Homebrewで入れると楽でした。

コマンドの使い方は go コマンドと同様です (gop run, gop build 等)。

gop run した場合、gopファイルをgoファイルにトランスパイルしてから実行されます。中間生成物のgoファイルは gop_autogen.go で確認できます。

main.gop
import "fmt"

func main() {
        fmt.Println("Hello, world!")
}
gop_autogen.go
package main

import fmt "fmt"

func main() {
//line main.gop:4
        fmt.Println("Hello, world!")
}

構文の違い

基本はGoと互換性がありますが、記述量を抑えるためのいくつかの構文が拡張されています。

関数呼び出しのかっこが不要

fmt.Println("Hello, world!")

fmt.Println "Hello, world!"

と書けます。後述のDSLを書く際に少し見栄えが良くなります。

(ちなみに、print系は組み込みでも定義されているので、fmtをimportせずに println でも呼び出せます)

コレクション

配列やマップのリテラルに型を書く必要がありません。

// 型は勝手に推論される
words := ["foo", "bar", "baz"] // []string
vals := ["Hi", 10] // []any

// mapも同様
{"Hello": 1, "xsw": 3}

for文

range の代わりに <- を使用します。

import "fmt"

func main() {
    words := ["foo", "bar", "baz"]

    for word <- words {
        fmt.Println(word)
    }

    for i <- 1:5 {
        fmt.Println(i)
    }
}

内包表記

内包表記も使えます。

fmt.Println([w[0:1] for w <- words]) // ["f", "b", "b"]

?によるエラーハンドリング

? を使うことで、エラーハンドリングを暗黙的に行うことができます。

func add(x, y string) (int, error) {
    return strconv.Atoi(x)? + strconv.Atoi(y)?, nil
}

このコードは以下と同様です。

func add(x, y string) (int, error) {
    xi, err := strconv.Atoi(x)
    if err != nil {
        return 0, err
    }
    yi, err := strconv.Atoi(y)
    if err != nil {
        return 0, err
    }
    return xi + yi, nil
}

これ、Rustで一番好きな構文なので「Goで使えたらいいな」といつも妄想してました、
もう if err != nil まみれとは言わせない

lambda

Goの関数リテラルよりもシンプルに書けます。

// ジェネリクスは未対応っぽい
func Map(nums []int, f func(int) int) []int {
        return [f(n) for n <- nums]
}

func main() {
        fmt.Println(Map([1,2,3], n => n * 2))

        // 普通のGoっぽくも書ける
        fmt.Println(Map([1,2,3], func(n int) int {return n * 2}))
}

演算子のオーバーロード

自作の型で演算子を定義できます。

import "fmt"

type MyInt int

func (i MyInt) +(other MyInt) MyInt {
        // そのまま i + other とすると無限ループするので注意!
        return MyInt((int(i) + int(other)) % 10)
}

func main() {
        a := MyInt(9)
        b := MyInt(3)
        fmt.Println(a + b) // 2
}

その他

Go+では、DSLのように特定の用途向けのフレームワークを作る機能(ClassFile)があります。
この機能を使って、Goの文法でシェルのようにコマンド実行ができるライブラリもあるようです。

...が、残念ながら最新版では互換性の問題で動作しませんでした。バージョンを下げても動かないのでやむなく断念... :cry:

おわりに

以上、Go+言語の紹介でした。
Goらしさは残しつつ、痒い所に手が届く文法が足されているのが嬉しいです。小さなツールをサクッと作るのに向いていそうです。

関連記事

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0