Bagaimana cara menemukan jenis objek di Go?


387

Bagaimana cara menemukan jenis objek di Go? Dalam Python, saya hanya menggunakan typeofuntuk mengambil jenis objek. Demikian pula dalam Go, apakah ada cara untuk menerapkan hal yang sama?

Ini adalah wadah tempat saya melakukan iterasi:

for e := dlist.Front(); e != nil; e = e.Next() {
    lines := e.Value
    fmt.Printf(reflect.TypeOf(lines))
}

Saya tidak bisa mendapatkan jenis garis objek dalam hal ini yang merupakan array dari string.


Referensi standar tidak bekerja di program saya. Seharusnya saya mencantumkan kode sumber bad saya.
Rahul

6
fmt.Printf("%T\n", var)
meh

Jawaban:


470

Paket refleksi Go memiliki metode untuk memeriksa jenis variabel.

Cuplikan berikut akan mencetak jenis pantulan string, integer, dan float.

package main

import (
    "fmt"
    "reflect"
)

func main() {

    tst := "string"
    tst2 := 10
    tst3 := 1.2

    fmt.Println(reflect.TypeOf(tst))
    fmt.Println(reflect.TypeOf(tst2))
    fmt.Println(reflect.TypeOf(tst3))

}

Keluaran:

Hello, playground
string
int
float64

lihat: http://play.golang.org/p/XQMcUVsOja untuk melihatnya dalam aksi.

Dokumentasi lebih lanjut di sini: http://golang.org/pkg/reflect/#Type


mencerminkan tidak bekerja untuk saya. Saya telah memperbarui pertanyaan. Saya telah memasukkan cuplikan kode dalam kasus ini.
Rahul

462

Saya menemukan 3 cara untuk mengembalikan tipe variabel saat runtime:

Menggunakan pemformatan string

func typeof(v interface{}) string {
    return fmt.Sprintf("%T", v)
}

Menggunakan paket refleksi

func typeof(v interface{}) string {
    return reflect.TypeOf(v).String()
}

Menggunakan pernyataan tipe

func typeof(v interface{}) string {
    switch v.(type) {
    case int:
        return "int"
    case float64:
        return "float64"
    //... etc
    default:
        return "unknown"
    }
}

Setiap metode memiliki kasus penggunaan terbaik yang berbeda:

  • pemformatan string - jejak pendek dan rendah (tidak perlu mengimpor paket mencerminkan)

  • mencerminkan paket - ketika membutuhkan detail lebih lanjut tentang jenis kami memiliki akses ke kemampuan refleksi penuh

  • jenis pernyataan - memungkinkan jenis pengelompokan, misalnya mengenali semua tipe int32, int64, uint32, uint64 sebagai "int"


3
Tampaknya Anda dapat menyingkirkan variabel t, jadi t := v.(type)menjadi v.(type), dan _ = ttidak lagi diperlukan.
Akavall

3
Berdasarkan tolok ukur barebones, pendekatan refleksi secara mengejutkan lebih efisien gist.github.com/mrap/7f08c9549289b6aea2923c27888e7e3e
Mike Rapadas

case 'T': p.fmt.fmtS(reflect.TypeOf(arg).String()). Paket fmt menggunakan mencerminkan untuk mencetak jenis
Fantasy_RQG

50

Gunakan paket mencerminkan :

Paket mencerminkan penerapan refleksi run-time, yang memungkinkan program untuk memanipulasi objek dengan tipe sewenang-wenang. Penggunaan tipikal adalah untuk mengambil nilai dengan antarmuka tipe statis {} dan mengekstrak informasi tipe dinamisnya dengan memanggil TypeOf, yang mengembalikan Tipe.

package main

import (
    "fmt"
    "reflect"
)

func main() {
    b := true
    s := ""
    n := 1
    f := 1.0
    a := []string{"foo", "bar", "baz"}

    fmt.Println(reflect.TypeOf(b))
    fmt.Println(reflect.TypeOf(s))
    fmt.Println(reflect.TypeOf(n))
    fmt.Println(reflect.TypeOf(f))
    fmt.Println(reflect.TypeOf(a))
}

Menghasilkan:

bool
string
int
float64
[]string

Tempat bermain

Contoh menggunakan ValueOf(i interface{}).Kind():

package main

import (
    "fmt"
    "reflect"
)

func main() {
    b := true
    s := ""
    n := 1
    f := 1.0
    a := []string{"foo", "bar", "baz"}

    fmt.Println(reflect.ValueOf(b).Kind())
    fmt.Println(reflect.ValueOf(s).Kind())
    fmt.Println(reflect.ValueOf(n).Kind())
    fmt.Println(reflect.ValueOf(f).Kind())
    fmt.Println(reflect.ValueOf(a).Index(0).Kind()) // For slices and strings
}

Menghasilkan:

bool
string
int
float64
string

Tempat bermain


mencerminkan hanya menampilkan tipe standar. Saya tidak bisa mendapatkan jenis elemen dari wadah daftar.
Rahul

Saya telah memperbarui jawaban saya untuk memasukkan sepotong string. Reflect berfungsi untuk semua jenis. Silakan baca dokumen: golang.org/pkg/reflect & blog.golang.org/laws-of-reflection seharusnya sudah cukup, meskipun ada banyak pertanyaan SO terkait dengan refleksi di Go yang dapat membantu Anda juga.
Intermernet

2
ughhh, bagaimana saya bisa menentukan apakah jenisnya adalah string? if reflect.TypeOf(err) == string?
Alexander Mills

43

Untuk mendapatkan representasi string:

Dari http://golang.org/pkg/fmt/

% T representasi Go-sintaks dari jenis nilai

package main
import "fmt"
func main(){
    types := []interface{} {"a",6,6.0,true}
    for _,v := range types{
        fmt.Printf("%T\n",v)
    }
}

Output:

string
int
float64
bool

pendekatan yang sangat pragmatis +1
Bijan

16

Saya akan menjauh dari pantulan. paket. Alih-alih gunakan% T

package main

import (
    "fmt"
)

func main() {
    b := true
    s := ""
    n := 1
    f := 1.0
    a := []string{"foo", "bar", "baz"}

    fmt.Printf("%T\n", b)
    fmt.Printf("%T\n", s)
    fmt.Printf("%T\n", n)
    fmt.Printf("%T\n", f)
    fmt.Printf("%T\n", a)
 }

13

Cara terbaik adalah menggunakan konsep refleksi di Google.
reflect.TypeOfmemberikan tipe bersamaan dengan nama paket
reflect.TypeOf().Kind()memberikan tipe garis bawah


1
Ini menurut saya adalah jawaban yang lebih baik
Ezio

9

Untuk menjadi singkat, silakan gunakan fmt.Printf("%T", var1) atau varian lainnya dalam paket fmt.


4

Anda dapat memeriksa jenis variabel / instance saat runtime baik menggunakan TypeOffungsi paket "mencerminkan" atau dengan menggunakan fmt.Printf():

package main

import (
   "fmt"
   "reflect"
)

func main() {
    value1 := "Have a Good Day"
    value2 := 50
    value3 := 50.78

    fmt.Println(reflect.TypeOf(value1 ))
    fmt.Println(reflect.TypeOf(value2))
    fmt.Println(reflect.TypeOf(value3))
    fmt.Printf("%T",value1)
    fmt.Printf("%T",value2)
    fmt.Printf("%T",value3)
}

4

Untuk mendapatkan jenis bidang dalam struct

package main

import (
  "fmt"
  "reflect"
)

type testObject struct {
  Name   string
  Age    int
  Height float64
}

func main() {
   tstObj := testObject{Name: "yog prakash", Age: 24, Height: 5.6}
   val := reflect.ValueOf(&tstObj).Elem()
   typeOfTstObj := val.Type()
   for i := 0; i < val.NumField(); i++ {
       fieldType := val.Field(i)
       fmt.Printf("object field %d key=%s value=%v type=%s \n",
          i, typeOfTstObj.Field(i).Name, fieldType.Interface(),
          fieldType.Type())
   }
}

Keluaran

object field 0 key=Name value=yog prakash type=string 
object field 1 key=Age value=24 type=int 
object field 2 key=Height value=5.6 type=float64

Lihat di IDE https://play.golang.org/p/bwIpYnBQiE


0

Anda dapat menggunakan reflect.TypeOf.

  • jenis dasar (misalnya: int, string): ia akan kembali namanya (misalnya: int, string)
  • struct: itu akan kembali sesuatu dalam format <package name>.<struct name>(misalnya: main.test)

0

Jika kita memiliki variabel ini:

var counter int = 5
var message string  = "Hello"
var factor float32 = 4.2
var enabled bool = false

1: fmt.Printf% T format: untuk menggunakan fitur ini Anda harus mengimpor "fmt"

fmt.Printf("%T \n",factor )   // factor type: float32

2: fungsi reflect.TypeOf : untuk menggunakan fitur ini Anda harus mengimpor "mencerminkan"

fmt.Println(reflect.TypeOf(enabled)) // enabled type:  bool

3: reflect.ValueOf (X) .Kind () : untuk menggunakan fitur ini Anda harus mengimpor "mencerminkan"

fmt.Println(reflect.ValueOf(counter).Kind()) // counter type:  int

0

Anda dapat menggunakan: interface{}..(type)seperti di taman bermain ini

package main
import "fmt"
func main(){
    types := []interface{} {"a",6,6.0,true}
    for _,v := range types{
        fmt.Printf("%T\n",v)
        switch v.(type) {
        case int:
           fmt.Printf("Twice %v is %v\n", v, v.(int) * 2)
        case string:
           fmt.Printf("%q is %v bytes long\n", v, len(v.(string)))
       default:
          fmt.Printf("I don't know about type %T!\n", v)
      }
    }
}


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.