반응형
Go에서 런타임에 해당 유형에서 구조체의 새 인스턴스를 만드는 방법은 무엇입니까?
Go에서 런타임에 객체 유형에서 객체의 인스턴스를 어떻게 생성합니까? 나는 당신이 또한 type먼저 물체 의 실제를 얻어야한다고 생각 합니까?
메모리를 절약하기 위해 게으른 인스턴스화를 시도하고 있습니다.
그렇게하려면 reflect.
package main
import (
"fmt"
"reflect"
)
func main() {
// one way is to have a value of the type you want already
a := 1
// reflect.New works kind of like the built-in function new
// We'll get a reflected pointer to a new int value
intPtr := reflect.New(reflect.TypeOf(a))
// Just to prove it
b := intPtr.Elem().Interface().(int)
// Prints 0
fmt.Println(b)
// We can also use reflect.New without having a value of the type
var nilInt *int
intType := reflect.TypeOf(nilInt).Elem()
intPtr2 := reflect.New(intType)
// Same as above
c := intPtr2.Elem().Interface().(int)
// Prints 0 again
fmt.Println(c)
}
int 대신 struct 유형으로 동일한 작업을 수행 할 수 있습니다. 아니면 정말. 맵 및 슬라이스 유형에 관해서는 new와 make의 차이점을 알고 있어야합니다.
으로 reflect.New자동 구조체 분야에서 사용 참조 유형을하지 않는 재귀 그 필드 유형을 (이 예에서는 재귀 구조체 정의를 참고) 초기화하려면, 다음과 같이 사용할 수 :
package main
import (
"fmt"
"reflect"
)
type Config struct {
Name string
Meta struct {
Desc string
Properties map[string]string
Users []string
}
}
func initializeStruct(t reflect.Type, v reflect.Value) {
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
ft := t.Field(i)
switch ft.Type.Kind() {
case reflect.Map:
f.Set(reflect.MakeMap(ft.Type))
case reflect.Slice:
f.Set(reflect.MakeSlice(ft.Type, 0, 0))
case reflect.Chan:
f.Set(reflect.MakeChan(ft.Type, 0))
case reflect.Struct:
initializeStruct(ft.Type, f)
case reflect.Ptr:
fv := reflect.New(ft.Type.Elem())
initializeStruct(ft.Type.Elem(), fv.Elem())
f.Set(fv)
default:
}
}
}
func main() {
t := reflect.TypeOf(Config{})
v := reflect.New(t)
initializeStruct(t, v.Elem())
c := v.Interface().(*Config)
c.Meta.Properties["color"] = "red" // map was already made!
c.Meta.Users = append(c.Meta.Users, "srid") // so was the slice.
fmt.Println(v.Interface())
}
reflect.Zero()구조체 유형의 0 값 표현을 반환하는 것을 사용할 수 있습니다 . (당신이 한 경우와 유사 var foo StructType) 이것은 reflect.New()후자가 구조체를 동적으로 할당하고 다음과 유사한 포인터를 제공하기 때문에 다릅니다.new(StructType)
다음은 Evan Shaw와 같은 기본 예제이지만 구조체가 있습니다.
package main
import (
"fmt"
"reflect"
)
func main() {
type Product struct {
Name string
Price string
}
var product Product
productType := reflect.TypeOf(product) // this type of this variable is reflect.Type
productPointer := reflect.New(productType) // this type of this variable is reflect.Value.
productValue := productPointer.Elem() // this type of this variable is reflect.Value.
productInterface := productValue.Interface() // this type of this variable is interface{}
product2 := productInterface.(Product) // this type of this variable is product
product2.Name = "Toothbrush"
product2.Price = "2.50"
fmt.Println(product2.Name)
fmt.Println(product2.Price)
}
newacct의 응답에 따라 Reflect.zero를 사용하면 다음과 같습니다.
var product Product
productType := reflect.TypeOf(product) // this type of this variable is reflect.Type
productValue := reflect.Zero(productType) // this type of this variable is reflect.Value
productInterface := productValue.Interface() // this type of this variable is interface{}
product2 := productInterface.(Product) // the type of this variable is Product
이것은 이동 중 반사의 기본에 대한 훌륭한 기사 입니다.
필요하지 않으며 reflect동일한 인터페이스를 공유하는 경우 팩토리 패턴으로 쉽게 수행 할 수 있습니다.
package main
import (
"fmt"
)
// Interface common for all classes
type MainInterface interface {
GetId() string
}
// First type of object
type FirstType struct {
Id string
}
func (ft *FirstType) GetId() string {
return ft.Id
}
// FirstType factory
func InitializeFirstType(id string) MainInterface {
return &FirstType{Id: id}
}
// Second type of object
type SecondType struct {
Id string
}
func (st *SecondType) GetId() string {
return st.Id
}
// SecondType factory
func InitializeSecondType(id string) MainInterface {
return &SecondType{Id: id}
}
func main() {
// Map of strings to factories
classes := map[string]func(string) MainInterface{
"first": InitializeFirstType,
"second": InitializeSecondType,
}
// Create a new FirstType object with value of 10 using the factory
newObject := classes["first"]("10")
// Show that we have the object correctly created
fmt.Printf("%v\n", newObject.GetId())
// Create a new SecondType object with value of 20 using the factory
newObject2 := classes["second"]("20")
// Show that we have the object correctly created
fmt.Printf("%v\n", newObject2.GetId())
}
반응형
'Program Club' 카테고리의 다른 글
| 특정 디렉토리의 경로없이 파일 이름 가져 오기 (0) | 2020.12.11 |
|---|---|
| Node.js-Mongoose로 관계 만들기 (0) | 2020.12.11 |
| CSS-최대 Z- 색인 값 (0) | 2020.12.11 |
| 현재 IPython 노트북 이름을 얻는 방법 (0) | 2020.12.11 |
| 단일 프로세서 시스템에서 멀티 스레딩을 구현할 수 있습니까? (0) | 2020.12.11 |