데이터 (유형 인터페이스 {})를 유형 문자열로 변환 할 수 없음 : 유형 어설 션 필요
나는 꽤나 새로 왔으며이 알림 패키지를 가지고 놀고있었습니다 .
처음에는 다음과 같은 코드가있었습니다.
func doit(w http.ResponseWriter, r *http.Request) {
notify.Post("my_event", "Hello World!")
fmt.Fprint(w, "+OK")
}
위 Hello World!
의 함수에는 개행 문자를 추가하고 싶었습니다 doit
. 왜냐하면 꽤 간단 하기는하지만 handler
나중에 다음과 같이하기 때문입니다.
func handler(w http.ResponseWriter, r *http.Request) {
myEventChan := make(chan interface{})
notify.Start("my_event", myEventChan)
data := <-myEventChan
fmt.Fprint(w, data + "\n")
}
후 go run
:
$ go run lp.go
# command-line-arguments
./lp.go:15: invalid operation: data + "\n" (mismatched types interface {} and string)
약간의 인터넷 검색 후 나는 이 질문을 SO 에서 발견 했다 .
그런 다음 코드를 다음과 같이 업데이트했습니다.
func handler(w http.ResponseWriter, r *http.Request) {
myEventChan := make(chan interface{})
notify.Start("my_event", myEventChan)
data := <-myEventChan
s:= data.(string) + "\n"
fmt.Fprint(w, s)
}
이것이 내가해야했던 일입니까? 컴파일러 오류가 사라 졌으므로 꽤 좋을 것 같습니다. 이것이 효율적입니까? 다르게해야합니까?
Go 사양 에 따르면 :
인터페이스 유형의 표현식 x와 유형 T의 경우, 기본 표현식 x. (T)는 x가 nil이 아니며 x에 저장된 값이 T 유형임을 주장합니다.
"유형 어설 션"을 사용하면 인터페이스 값에 특정 콘크리트 유형이 포함되어 있거나 콘크리트 유형이 다른 인터페이스를 충족한다고 선언 할 수 있습니다.
귀하의 예에서 데이터를 주장하고 있었으며 (type interface {}) 콘크리트 유형 문자열이 있습니다. 당신이 잘못되면, 프로그램은 런타임에 패닉합니다. 효율성에 대해 걱정할 필요가 없습니다. 검사는 두 개의 포인터 값을 비교하기 만하면됩니다.
문자열인지 확실하지 않은 경우 두 반환 구문을 사용하여 테스트 할 수 있습니다.
str, ok := data.(string)
데이터가 문자열이 아닌 경우 ok는 false입니다. 그런 다음과 같은 명령문을 if 문으로 랩핑하는 것이 일반적입니다.
if str, ok := data.(string); ok {
/* act on str */
} else {
/* not string */
}
유형 어설 션
이것은 type assertion
golang 으로 알려져 있으며 일반적인 관행입니다.
형식 어설 션은 인터페이스 값의 기본 구체적인 값에 대한 액세스를 제공합니다.
t := i.(T)
이 명령문은 인터페이스 값 i가 구체적 유형 T를 보유하고 기본 T 값을 변수 t에 지정 한다고 주장합니다 .
내가 T를 보유하지 않으면, 진술은 공황을 유발할 것입니다.
인터페이스 값에 특정 유형이 있는지 여부를 테스트하기 위해 유형 어설 션은 기본 값과 어설 션 성공 여부를보고하는 부울 값의 두 값을 반환 할 수 있습니다.
t, ok := i.(T)
i에 T가 있으면 t가 기본 값이되고 ok가 true가됩니다.
그렇지 않은 경우 ok는 false이고 t는 T 유형의 0 값이며 패닉은 발생하지 않습니다.
참고 : 값 i
은 인터페이스 유형이어야합니다 .
함정
Even if i
is an interface type, []i
is not interface type. As a result, in order to convert []i
to its value type, we have to do it individually:
// var items []i
for _, item := range items {
value, ok := item.(T)
dosomethingWith(value)
}
Performance
As for performance, it can be slower than direct access to the actual value as show in this stackoverflow answer.
//an easy way:
str := fmt.Sprint(data)
'development' 카테고리의 다른 글
OS X 10.11의 PDFtk 서버 (0) | 2020.06.06 |
---|---|
Android에서 자체 URI 체계를 구현하는 방법 (0) | 2020.06.06 |
텍스트 모드에서 Emacs에서 4 개의 들여 쓰기 설정 (0) | 2020.06.06 |
관찰자, 발행 / 구독 및 데이터 바인딩의 차이점 (0) | 2020.06.06 |
주어진 접미사로 끝나지 않는 문자열에 대한 정규식 (0) | 2020.06.06 |