Goでの型キャスト

私はいつも使っているシンプルなライブラリを共有しています。 GoはJSONでうまく機能しますが、多くの場合、インターフェイス{}を何らかのタイプにキャストするための一連の関数がありません。 JSONマーシャリングの標準的な構造を定義したとしても、時間が経つにつれて追加のフィールドを定義し、Extra interface {}と呼ぶ必要があります。 それは私たちが実際に持っているものについてです。



type Message struct { store bool Type string `json:"type"` Session string `json:"session,omitempty"` Data map[string]string `json:"data,omitempty"` Text string `json:"text,omitempty"` Name string `json:"name,omitempty"` Time int64 `json:"time,omitempty,string"` ServerId int64 `json:"serverId,omitempty,string"` Extra interface{} `json:"extra,omitempty"` }
      
      







なぜ標準的なアプローチがうまく機能しないのか。 JSONの主なソースは、WebブラウザーからのJavaScriptです。 JavaScriptはすべての数値をdoubleとして表します。 JavaScriptは、たとえば、int64を丸めることができます



  fmt.Println(time.Now().UnixNano())
      
      





1428308621182823638を発行します

 javascript:alert(1428308621182823638)
      
      





これはすでに





そのため、一部の数字は、 `json:"、string "`タグを使用して文字列として定義できますが、ユーザーが数字を引用符で囲まないと機能しません。



 package main import ( "encoding/json" "fmt" ) type X struct { Time int64 `json:"time,omitempty,string"` } func main() { var m1 map[string]interface{} e := json.Unmarshal([]byte(`{"x":1,"y":{}}`), &m1) fmt.Println(e, m1) var x X e = json.Unmarshal([]byte(`{"time":1}`), &x) fmt.Println(e, x) e = json.Unmarshal([]byte(`{"time":"1"}`), &x) fmt.Println(e, x) }
      
      





遊び場



{「時間」:1}-動作しませんでした



ドキュメントが数字を引用符で囲む必要があると太字の斜体で記載されている場合でも、Webサービスサポートがどれだけの労力を費やすか想像することは困難です。



逆の状況も可能です.JSONで数字が必要な場合、ユーザーは(PHPの動作で)<input />タグが入力された数字を文字列として返すため、ユーザーは数字を文字列として渡すことができます。したがって、文字列は数字の代わりにWebサービスのJSONに入ることができます



多くの場合、より速く書くのが簡単です

  var m1 map[string]interface{} e := json.Unmarshal([]byte(`{"x":1,"y":{}}`), &m1) fmt.Println(e, m1)
      
      







インターフェイス{}を文字列または[]インターフェイス{}にキャストするための十分な簡潔な関数がないため、 pyraconvパッケージで定義しました。



私の関数はnilを返しません。 たとえば、pyraconv.ToStringArray()は、nilの代わりに常に[] string {}を返します。pyraconv.ToInt64()-常に1つのint64パラメーターを返します。つまり、int(pyraconv.ToInt64(x))を記述できます。



JSONをこの方法でいつでもどこでも解析するつもりはありませんが、このコードは非常に便利です。



機能リスト:



 func ToBool(i1 interface{}) bool
      
      





ToBoolはインターフェイス{}をboolに変換します



 func ToInt64(i1 interface{}) int64
      
      





ToInt64はインターフェイス{}をint64に変換します



 func ToInterfaceArray(i1 interface{}) []interface{}
      
      





ToInterfaceArrayはインターフェイス{}を[]インターフェイス{}に変換し、nilを返しません



 func ToInterfaceMap(i1 interface{}) map[string]interface{}
      
      





ToInterfaceMapは、インターフェイス{}をマップ[string]インターフェイス{}に変換し、nilを返しません



 func ToString(i1 interface{}) string
      
      





ToStringはインターフェイス{}を文字列に変換します



 func ToStringArray(i1 interface{}) []string
      
      





ToStringArrayはインターフェイス{}を[]文字列に変換し、nilを返しません



 func ToStringMap(i1 interface{}) map[string]string
      
      





ToStringMapは、インターフェイス{}をマップ[string]文字列に変換し、nilを返しません



 func CloneObject(a, b interface{})
      
      





CloneObjectは、gobパッケージからのシリアル化を使用してオブジェクトのコピーを作成します。 ロックメカニズムを使用するよりも、並列処理のためにオブジェクトのコピーをgourutinに転送する方が効率的です。



JSONを処理するときにpyraconvを使用するWebサービスハンドラーの例。



 func handle_ctrl_channel(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { b, e := ioutil.ReadAll(r.Body) if e != nil { fmt.Fprintf(w, `{ "error": true, "no":1 }`) return } var m1 map[string]interface{} e = json.Unmarshal(b, &m1) if e != nil { fmt.Fprintf(w, `{ "error": true, "no":2 }`) return } cmd := m1["cmd"] if cmd == "add" { id := pyraconv.ToString(m1["id"]) url := pyraconv.ToStringArray(m1["urls"]) service.UpdateStream(url, id) return } if cmd == "delete" { id := pyraconv.ToString(m1["id"]) service.DelStream(id) return } } }
      
      







健康にフォークピラコン 。 いただきます。



 go get github.com/CossackPyra/pyraconv
      
      






All Articles