1. ホーム
  2. 行く

[解決済み】データ(型インターフェース{})を文字列に変換できない:型アサーションが必要

2022-04-11 17:18:06

質問

私は囲碁の初心者ですが、このように遊んでいました。 通知 パッケージを使用します。

最初はこんな感じのコードでした。

func doit(w http.ResponseWriter, r *http.Request) {
    notify.Post("my_event", "Hello World!")
    fmt.Fprint(w, "+OK")
}

に改行を追加したかったのです。 Hello World! という関数ではありません。 doit というのも、これはとてもつまらないことですが、上記の handler の後に、以下のような感じです。

func handler(w http.ResponseWriter, r *http.Request) {
    myEventChan := make(chan interface{})
    notify.Start("my_event", myEventChan)
    data := <-myEventChan
    fmt.Fprint(w, data + "\n")
}

go run :

$ go run lp.go 
# command-line-arguments
./lp.go:15: invalid operation: data + "\n" (mismatched types interface {} and string)

ちょっとググってみたら SOでこの質問 .

そして、コードを更新しました。

func handler(w http.ResponseWriter, r *http.Request) {
    myEventChan := make(chan interface{})
    notify.Start("my_event", myEventChan)
    data := <-myEventChan
    s:= data.(string) + "\n"
    fmt.Fprint(w, s)
}

こんな感じでいいんでしょうか?コンパイラのエラーはなくなったので、かなりいいんじゃないでしょうか?これって効率的なの?もっと違うやり方がいいのか?

どのように解決するのですか?

によると 囲碁の仕様 :

インターフェース型の式xと型Tに対して、一次式x.(T)はxがnilでないこと、xに格納された値が型Tであることを保証する。

型アサーションは、あるインターフェースの値がある具象型を含むこと、またはその具象型が他のインターフェースを満たすことを宣言することができます。

この例では、データ(型interface{})が具象型stringを持つことを表明していますね。もし、間違っていたら、プログラムは実行時にパニックになります。チェックは2つのポインタの値を比較するだけなので、効率を気にする必要はない。

もし、文字列かどうかわからない場合は、two return構文を使ってテストすることができました。

str, ok := data.(string)

dataが文字列でない場合、okはfalseになります。そこで、このような文は、次のようにif文でくくるのが一般的である。

if str, ok := data.(string); ok {
    /* act on str */
} else {
    /* not string */
}