나는 아주 새로운 것이었고 나는이 알림 패키지를 가지고 놀고있었습니다 .
처음에는 다음과 같은 코드가있었습니다.
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
은 인터페이스 유형이어야합니다 .
함정
i
인터페이스 유형 인 경우에도 인터페이스 유형 []i
이 아닙니다. 결과적으로 []i
값 유형 으로 변환 하려면 개별적으로 수행해야합니다.
// var items []i
for _, item := range items {
value, ok := item.(T)
dosomethingWith(value)
}
공연
성능에 관해서는 이 stackoverflow answer 에 표시된 것처럼 실제 값에 직접 액세스하는 것보다 느릴 수 있습니다 .
답변
//an easy way:
str := fmt.Sprint(data)
답변
@ ρяσѕρєя의 요청에 따라 https://golang.org/pkg/fmt/#Sprint 에서 설명을 찾을 수 있습니다 . 관련 설명은 https://stackoverflow.com/a/44027953/12817546 및 https://stackoverflow.com/a/42302709/12817546 에서 찾을 수 있습니다 . @Yuanbo의 답변은 다음과 같습니다.
package main
import "fmt"
func main() {
var data interface{} = 2
str := fmt.Sprint(data)
fmt.Println(str)
}