Go가 암시 적으로 변환 []T
할 []interface{}
때 암시 적으로 변환하지 않는 이유가 궁금 T
합니다 interface{}
. 누락 된이 전환에 대해 사소한 것이 있습니까?
예:
func foo([]interface{}) { /* do something */ }
func main() {
var a []string = []string{"hello", "world"}
foo(a)
}
go build
불평하다
함수 인수에서 (] [type]을 (를) 유형 [] 인터페이스 {}로 사용할 수 없습니다.
그리고 명시 적으로하려고하면 동일한 일이 b := []interface{}(a)
불평합니다.
(유형 [] 문자열)을 유형 [] 인터페이스 {} (으)로 변환 할 수 없습니다
그래서이 변환을해야 할 때마다 (많은 것으로 보입니다), 나는 다음과 같은 일을하고 있습니다 :
b = make([]interface{}, len(a), len(a))
for i := range a {
b[i] = a[i]
}
이 작업을 수행하는 더 좋은 방법이나 이러한 변환에 도움이되는 표준 라이브러리 기능이 있습니까? 정수 또는 문자열 목록을 가져올 수있는 함수를 호출 할 때마다 4 개의 추가 코드 줄을 작성하는 것은 어리석은 것처럼 보입니다.
답변
Go에는 구문이 복잡하고 비용이 많이 드는 작업을 숨겨서는 안된다는 일반적인 규칙이 있습니다. a string
로 변환하는 interface{}
것은 O (1) 시간 안에 이루어집니다. A 변환 []string
내지 An은 interface{}
슬라이스는 여전히 하나 개의 값이기 때문에 같은 O (1) 시간 수행된다. 그러나 슬라이스의 각 요소를로 변환해야하기 때문에 a []string
를 a () 로 변환하는 []interface{}
시간은 O (n) interface{}
입니다.
이 규칙의 한 가지 예외는 문자열 변환입니다. a string
를 a []byte
또는 a 로 변환 할 때 변환 []rune
이 “구문”인 경우에도 O (n)이 작동합니다.
이 변환을 수행 할 표준 라이브러리 기능은 없습니다. 리플렉션으로 만들 수는 있지만 3 줄 옵션보다 느립니다.
리플렉션이 포함 된 예 :
func InterfaceSlice(slice interface{}) []interface{} {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic("InterfaceSlice() given a non-slice type")
}
ret := make([]interface{}, s.Len())
for i:=0; i<s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret
}
가장 좋은 방법은 질문에 제공 한 코드 줄을 사용하는 것입니다.
b := make([]interface{}, len(a))
for i := range a {
b[i] = a[i]
}
답변
누락되는 일이 있다는 것입니다 T
및 interface{}
값 보유하고있는 T
메모리의 다른 표현이 너무 하찮게 변환 할 수없는 한을.
유형의 변수는 T
메모리의 값입니다. 연관된 유형 정보가 없습니다 (Go에서는 모든 변수에 런타임 시가 아닌 컴파일 타임에 알려진 단일 유형이 있음). 다음과 같이 메모리에 표시됩니다.
- 값
interface{}
형 들고 변수는 T
이와 같은 메모리에 표현되는
- 유형에 대한 포인터
T
- 값
그래서 원래의 질문에 돌아 오는 왜 이동 does’t 암시 적 변환 []T
에 []interface{}
?
메모리 내 레이아웃이 완전히 다르기 때문에 사소한 작업 인 새 값 조각을 만들려면 변환 []T
해야 합니다.[]interface{}
interface {}
답변
공식 설명은 다음과 같습니다. https://github.com/golang/go/wiki/InterfaceSlice
var dataSlice []int = foo()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
interfaceSlice[i] = d
}
답변
interface{}
대신 시도하십시오 . 슬라이스로 다시 캐스팅하려면
func foo(bar interface{}) {
s := bar.([]string)
// ...
}
답변
interface{}
모든 유형으로 변환하십시오 .
통사론:
result := interface.(datatype)
예:
var employee interface{} = []string{"Jhon", "Arya"}
result := employee.([]string) //result type is []string.
답변
코드를 더 단축해야하는 경우 도우미를위한 새로운 유형을 만들 수 있습니다.
type Strings []string
func (ss Strings) ToInterfaceSlice() []interface{} {
iface := make([]interface{}, len(ss))
for i := range ss {
iface[i] = ss[i]
}
return iface
}
그때
a := []strings{"a", "b", "c", "d"}
sliceIFace := Strings(a).ToInterfaceSlice()
답변
