Skip to content

Go バインディング

github.com/libraz/go-suzume モジュールは Suzume の Go バインディングです。Go のサービスやコマンドラインツールから、JavaScript/WASM パッケージを介さずに同じ日本語トークナイザーを使えます。

このバインディングはネイティブ C++ コアを薄く包んだ cgo レイヤーです。コア辞書とユーザー辞書は go:embed でモジュールに埋め込まれ、起動時に自動で解析器から参照できる状態になるため、ビルドした実行バイナリに外部辞書ファイルは不要です。

必要環境

  • Go 1.26 以上
  • CGO 有効、かつ C++17 コンパイラ(GCC 8+、Clang 10+、Apple Clang 12+)
  • CMake 3.15 以上(初回の静的ライブラリビルドに使用)

Python ホイールと違いコンパイル済みバイナリは同梱されておらず、Suzume の静的ライブラリを一度だけ手元でソースからビルドします。

インストール

静的ライブラリと辞書はどちらも C++ ソースから生成され、Go モジュールには含まれません。そのため go get だけではビルドできません。リポジトリをクローンして一度ビルドします。

bash
git clone https://github.com/libraz/go-suzume.git
cd go-suzume
make lib    # Suzume の C++ ソースを取得して libsuzume.a をビルド
make test   # 任意: テストを実行

利用側のモジュールからは、このチェックアウトを参照します。

bash
go mod edit -replace github.com/libraz/go-suzume=/path/to/go-suzume
go get github.com/libraz/go-suzume

ビルド成果物はチェックアウト先に書き込まれるため、書き込み可能なディレクトリに置いてください。Go のモジュールキャッシュは読み取り専用なので、そこにはビルドできません。

クイックスタート

パッケージ名は suzume です。New() で解析器を作成し、defer s.Close() でネイティブハンドルを確実に解放して、解析された形態素を反復処理します。

go
package main

import (
	"fmt"
	"log"

	"github.com/libraz/go-suzume"
)

func main() {
	s, err := suzume.New()
	if err != nil {
		log.Fatal(err)
	}
	defer s.Close()

	for _, m := range s.Analyze("東京都に住んでいます") {
		fmt.Printf("%s\t%s\t%s\n", m.Surface, m.POS, m.BaseForm)
	}
}

Analyze()[]Morpheme スライスを返します。入力から形態素が得られない場合も、呼び出しが失敗した場合も nil になり、戻り値だけでは区別できません。LastError() も確実な判定には使えません。ネイティブの診断は現在の OS スレッドに属し、値を読む前に Go ランタイムがゴルーチンを別スレッドへ移す可能性があるためです。Close() は何度呼んでも安全で、ファイナライザによる解放も予備として用意されていますが、明示的に defer するのが想定された使い方です。

インスタンスはネイティブ側の可変状態を保持しており、並行呼び出しには安全ではありません。ゴルーチンごとに 1 インスタンスを使うか、アクセスを直列化してください。別々のインスタンスは並行に動作でき、作成コストも小さいものです。

埋め込み辞書

パッケージの init 時に、埋め込まれた辞書はコンテンツアドレス方式のキャッシュディレクトリへ書き出され、SUZUME_DATA_DIR 経由でコアに渡されます。プログラム開始前に自分で SUZUME_DATA_DIR を設定していればそちらが優先され、埋め込み辞書は使われません。

解析モード

NewWithExtendedOptions() を使うと、分割モード・原形化・複合語結合まで含めて制御できます。ExtendedOptions のゼロ値はライブラリの既定値と一致しない(原形化と大文字小文字・ヴの保持が無効になってしまう)ため、DefaultExtendedOptions() を起点にしてください。

go
opts := suzume.DefaultExtendedOptions()
opts.Mode = suzume.ModeSearch // 検索向けに分割し、名詞複合語を結合
opts.MergeCompounds = true

s, err := suzume.NewWithExtendedOptions(opts)
if err != nil {
	log.Fatal(err)
}
defer s.Close()

指定できるモードは ModeNormal(既定)、ModeSearchModeSplit です。各モードが分割に与える影響は 解析モード を参照してください。

正規化だけを調整したい場合は NewWithOptions(Options) が使えます。PreserveVuPreserveCasePreserveSymbols の 3 つのトグルだけを受け取り、モードと原形化はライブラリの既定値のままにします。PreserveSymbols が制御するのは句読点などの SYMBOL トークンで、内容を持つ記号と絵文字は設定にかかわらず OTHER として残ります。

Morpheme のフィールド

Analyze()Morpheme 構造体のスライスを返します。

フィールド説明
Surfacestringテキスト中に現れる表層形
POSstring英語の品詞(大文字、例: NOUN
BaseFormstring辞書形・原形
POSJastring日本語の品詞(例: 名詞)
ConjTypestring活用型。IsConjugatable が true でも空文字列の場合あり
ConjFormstring活用形。IsConjugatable が true の場合に意味を持つ
ExtendedPOSstring安定した拡張品詞コード(例: VERB_連用
Startint正規化後テキストにおける開始文字オフセット
Endint正規化後テキストにおける終了文字オフセット
IsUserDictboolユーザー辞書にマッチした場合 true
IsFormalNounboolこと・もの などの形式名詞で true
IsLowInfoboolタグ生成向けに低情報量と判定された場合 true
IsUnknownbool未知語候補として生成された場合 true
IsFromDictionaryboolいずれかの辞書にマッチした場合 true
IsConjugatablebool活用フィールドが意味を持つ場合 true
Scorefloat32解析器が用いる候補スコア・コスト

IsConjugatable は動詞・形容詞だけでなく助動詞でも true になります。活用可能な形態素でも、該当する活用型がなければ ConjType は空文字列です。

POSExtendedPOS の全一覧は API リファレンス を参照してください。

タグ生成

GenerateTags() はテキストからキーワードタグを抽出します。既定では内容語(名詞、動詞、形容詞、副詞)を残し、助詞、助動詞、形式名詞、低情報量の語を除外します。

go
for _, t := range s.GenerateTags("東京都の天気予報を確認する") {
	fmt.Printf("%s (%s)\n", t.Tag, t.POS)
}

結果はそれぞれ Tag 構造体で、Tag(キーワードのテキスト)と POS(その品詞)の 2 フィールドを持ちます。

GenerateTagsWithOptions()TagOptions 構造体を受け取ります。TagOptions のゼロ値はすべての除外フィルターが無効になり、ライブラリの既定値と一致しないため、DefaultTagOptions() を起点にしてください。POSFilter フィールドは POSNounPOSVerbPOSAdjectivePOSAdverb 定数を組み合わせるビットマスクです(0 = すべて)。

go
opts := suzume.DefaultTagOptions()
opts.POSFilter = suzume.POSNoun | suzume.POSVerb // 名詞と動詞のみ
opts.MaxTags = 10                                // 上位 10 件のタグのみ残す

tags := s.GenerateTagsWithOptions("美味しいラーメンを食べた", opts)

残りの TagOptions フィールドとライブラリの既定値は次のとおりです。

フィールド既定値説明
POSFilteruint80対象とする品詞のビットマスク(0 = すべて)
ExcludeBasicboolfalse原形がひらがなのみの語を除外
UseLemmabooltrue表層形ではなく原形(辞書形)を使う
MinLengthint2タグの最小文字数
MaxTagsint0タグの最大件数(0 = 無制限)
ExcludeParticlesbooltrue助詞を除外
ExcludeAuxiliariesbooltrue助動詞を除外
ExcludeFormalNounsbooltrueこと・もの などの形式名詞を除外
ExcludeLowInfobooltrue低情報量の語を除外
RemoveDuplicatesbooltrue重複するタグを除去

ユーザー辞書

LoadUserDictionary() で、現行の TSV 形式からカスタム語を実行時に追加できます。従来の 3 列 CSV も受け付けます。

go
source := []byte("東京公園\tNOUN\n点検する\tVERB\tSURU\n")
if err := s.LoadUserDictionary(source); err != nil {
	log.Fatal(err)
}

for _, m := range s.Analyze("東京公園を点検する") {
	fmt.Println(m.Surface, m.POS, m.IsUserDict)
}

コンパイル済みのバイナリ .dic 辞書は、LoadBinaryDictionary() でメモリから読み込めます。

go
data, err := os.ReadFile("custom.dic")
if err != nil {
	log.Fatal(err)
}
if err := s.LoadBinaryDictionary(data); err != nil {
	log.Fatal(err)
}

どちらのメソッドも、読み込みに失敗すると非 nil の error を返します。DictionaryWarnings() は、インスタンス作成時の自動読み込みと、その後のソース/バイナリ辞書読み込みで発生した警告を返します(ない場合は nil)。一部の行だけを受理したソース辞書は、エラーを返さずに警告を追加する場合があります。

go
for _, w := range s.DictionaryWarnings() {
	fmt.Println("警告:", w)
}

API 概要

パッケージレベルの関数:

関数説明
New() (*Suzume, error)既定オプションで解析器を作成
NewWithOptions(opts Options) (*Suzume, error)正規化トグルのみ指定して作成
NewWithExtendedOptions(opts ExtendedOptions) (*Suzume, error)モード・原形化・複合語結合まで指定して作成
DefaultExtendedOptions() ExtendedOptionsライブラリ既定値の ExtendedOptions(起点として使用)
DefaultTagOptions() TagOptionsライブラリ既定値の TagOptions(起点として使用)
Version() stringネイティブ Suzume ライブラリのバージョン文字列
LastError() string現在の OS スレッドのネイティブ診断。Go から後で失敗原因を確認する用途には不確実
LastErrorCode() ErrorCode現在の OS スレッドの診断コード。スレッドに関する制約は LastError() と同じ

*Suzume のメソッド:

メソッド説明
Analyze(text string) []Morphemeテキストを解析(Morpheme のフィールドを参照)
GenerateTags(text string) []Tag既定フィルターでキーワード Tag を抽出
GenerateTagsWithOptions(text string, opts TagOptions) []Tagフィルターや件数制限を指定して Tag を抽出
LoadUserDictionary(data []byte) errorTSV または従来 CSV のユーザー辞書を読み込む
LoadBinaryDictionary(data []byte) errorバイナリ .dic 辞書を読み込む
DictionaryWarnings() []string作成時と実行時の辞書読み込み警告
Close()ネイティブハンドルを解放(何度呼んでも安全)

関連ページ