จะค้นหาประเภทของวัตถุใน Go ได้อย่างไร?


387

ฉันจะค้นหาประเภทของวัตถุใน Go ได้อย่างไร ใน Python ฉันใช้typeofเพื่อดึงข้อมูลประเภทของวัตถุ ในทำนองเดียวกันใน Go มีวิธีดำเนินการเหมือนกันหรือไม่

นี่คือคอนเทนเนอร์ที่ฉันกำลังวนซ้ำ:

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

ฉันไม่สามารถรับชนิดของวัตถุในกรณีนี้ซึ่งเป็นอาร์เรย์ของสตริง


การอ้างอิงมาตรฐานไม่ได้ทำงานในโปรแกรมของฉัน ฉันควรรวมซอร์สโค้ดที่ไม่ดีของฉันด้วย
ราหุล

5
fmt.Printf("%T\n", var)
Meh

คำตอบ:


470

แพคเกจ Go reflection มีวิธีการตรวจสอบชนิดของตัวแปร

ตัวอย่างต่อไปนี้จะพิมพ์ประเภทการสะท้อนของสตริงจำนวนเต็มและลอย

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))

}

เอาท์พุท:

Hello, playground
string
int
float64

ดู: http://play.golang.org/p/XQMcUVsOjaเพื่อดูการทำงาน

เอกสารเพิ่มเติมที่นี่: http://golang.org/pkg/reflect/#Type


สะท้อนให้เห็นถึงไม่ทำงานสำหรับฉัน ฉันได้อัปเดตคำถามแล้ว ฉันได้รวมข้อมูลโค้ดไว้ในกรณีนี้
ราหุล

462

ฉันพบ 3 วิธีในการคืนค่าชนิดของตัวแปรเมื่อรันไทม์:

ใช้การจัดรูปแบบสตริง

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

ใช้แพ็คเกจสะท้อนแสง

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

การใช้การยืนยันประเภท

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

ทุกวิธีมีกรณีการใช้ที่ดีที่สุดที่แตกต่างกัน:

  • การจัดรูปแบบสตริง - รอยเท้าสั้นและต่ำ (ไม่จำเป็นต้องนำเข้าสะท้อนแพคเกจ)

  • แพคเกจ reflect - เมื่อต้องการรายละเอียดเพิ่มเติมเกี่ยวกับประเภทที่เราสามารถเข้าถึงความสามารถในการสะท้อนเต็ม

  • การยืนยันประเภท - อนุญาตการจัดกลุ่มประเภทเช่นรู้จักชนิดทั้งหมดของ int32, int64, uint32, uint64 เป็น "int"


3
ดูเหมือนว่าคุณสามารถกำจัดตัวแปรtได้ดังนั้นจึงt := v.(type)กลายเป็นv.(type)และ_ = tไม่ต้องการอีกต่อไป
Akavall

3
ขึ้นอยู่กับเกณฑ์มาตรฐานเปลือย
Mike Rapadas

case 'T': p.fmt.fmtS(reflect.TypeOf(arg).String()). แพคเกจ fmt ใช้การสะท้อนถึงประเภทการพิมพ์
Fantasy_RQG

50

ใช้แพ็คเกจการสะท้อนแสง :

แพคเกจสะท้อนให้เห็นถึงการดำเนินการสะท้อนให้เห็นถึงเวลาทำงานทำให้โปรแกรมในการจัดการวัตถุที่มีประเภทโดยพลการ การใช้งานทั่วไปคือการรับค่าด้วยส่วนติดต่อประเภทคงที่ {} และดึงข้อมูลประเภทแบบไดนามิกโดยการเรียก TypeOf ซึ่งจะส่งกลับประเภท

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))
}

ผลิต:

bool
string
int
float64
[]string

สนามเด็กเล่น

ตัวอย่างการใช้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
}

ผลิต:

bool
string
int
float64
string

สนามเด็กเล่น


สะท้อนเพียงแสดงประเภทมาตรฐาน ฉันไม่สามารถรับองค์ประกอบของคอนเทนเนอร์รายการได้
ราหุล

ฉันได้อัปเดตคำตอบของฉันเพื่อรวมส่วนของสตริง สะท้อนงานประเภทใดก็ได้ โปรดอ่านเอกสาร: golang.org/pkg/reflect & blog.golang.org/laws-of-reflectionน่าจะเพียงพอแม้ว่าจะมีคำถาม SO มากมายที่เกี่ยวข้องกับการสะท้อนกลับใน Go ซึ่งจะช่วยคุณได้เช่นกัน
Intermernet

2
ใช่ฉันจะทราบได้อย่างไรว่าประเภทนั้นเป็นสตริงหรือไม่ if reflect.TypeOf(err) == string?
Alexander Mills

43

ในการรับการแทนค่าสตริง:

จากhttp://golang.org/pkg/fmt/

% T การแสดงไวยากรณ์ไปของชนิดของค่า

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

ขาออก:

string
int
float64
bool

วิธีการปฏิบัติอย่างมาก +1
Bijan

16

ฉันจะอยู่ห่างจากภาพสะท้อน บรรจุภัณฑ์ ใช้% 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

วิธีที่ดีที่สุดคือใช้แนวคิดการสะท้อนภาพใน Google
reflect.TypeOfให้ประเภทพร้อมกับชื่อแพคเกจ
reflect.TypeOf().Kind()ให้ประเภทการขีดเส้นใต้


1
ฉันคิดว่านี่เป็นคำตอบที่ดีกว่า
Ezio


4

คุณสามารถตรวจสอบชนิดของตัวแปร / อินสแตนซ์ใด ๆ ที่รันไทม์โดยใช้TypeOfฟังก์ชันแพคเกจ "reflect" หรือโดยใช้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

เพื่อรับชนิดของฟิลด์ใน 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())
   }
}

เอาท์พุต

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

ดูใน IDE https://play.golang.org/p/bwIpYnBQiE


0

reflect.TypeOfคุณสามารถใช้

  • ประเภทพื้นฐาน (เช่น: int, string): มันจะส่งคืนชื่อ (เช่น: int, string)
  • struct: มันจะกลับมาบางสิ่งบางอย่างในรูปแบบ<package name>.<struct name>(เช่นmain.test)

0

หากเรามีตัวแปรนี้:

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

1: fmt.Printf% Tรูปแบบ: เพื่อใช้คุณสมบัตินี้คุณควรนำเข้า "fmt"

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

2: reflect.TypeOfฟังก์ชั่น: การใช้คุณสมบัตินี้คุณควรนำเข้า "reflect"

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

3: reflect.ValueOf (X) .Kind () : เพื่อใช้คุณสมบัตินี้คุณควรนำเข้า "reflect"

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

0

คุณสามารถใช้: interface{}..(type)เช่นเดียวกับในสนามเด็กเล่นนี้

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)
      }
    }
}


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.