golang.org/x/exp/jsonrpc2を使ってgoplsに接続する

最近golang.org/x/expjsonrpc2が追加されていることを知ったので試してみた。 pkg.go.dev

基本的な使い方としてはDialConnectionを作成し、

  • レスポンスが返ってくるメソッドはCall + Await
  • レスポンスが返ってこないメソッドはNotify

を呼べば良い。

Content-Lengthなんかの処理はConnectionOptionsがデフォルトで設定するHeaderFramerがやってくれる。

以前に書いたgoplsに接続するコードに比べるとだいぶスッキリした。 daisuzu.hatenablog.com

import (
    "context"
    "net"

    "golang.org/x/exp/jsonrpc2"
)

type Client struct {
    conn *jsonrpc2.Connection
}

func Connect(ctx context.Context, addr string, initializeParams map[string]any) (*Client, error) {
    conn, err := jsonrpc2.Dial(ctx,
        jsonrpc2.NetDialer("tcp", addr, net.Dialer{}),
        jsonrpc2.ConnectionOptions{}, // goplsに繋ぐ時は全てデフォルト値でOK
    )
    if err != nil {
        return nil, err
    }

    var initializeResult map[string]any // このサンプルではレスポンスを受け取るだけで使わない
    if err := conn.Call(ctx, "initialize", initializeParams).Await(ctx, &initializeResult); err != nil {
        return nil, err
    }

    if err := conn.Notify(ctx, "initialized", map[string]any{}); err != nil {
        return nil, err
    }

    return &Client{conn: conn}, nil
}

func (c *Client) Shutdown(ctx context.Context) error {
    return c.conn.Notify(ctx, "shutdown", map[string]any{})
}