구조체를 정의합니다 …
type Session struct {
playerId string
beehive string
timestamp time.Time
}
때로는 빈 세션을 할당합니다 (nil이 불가능하기 때문에)
session = Session{};
그런 다음 비어 있는지 확인하고 싶습니다.
if session == Session{} {
// do stuff...
}
분명히 이것은 작동하지 않습니다. 어떻게 작성합니까?
답변
모든 필드가 비교 가능 하므로 ==를 사용하여 0 값 복합 리터럴과 비교할 수 있습니다 .
if (Session{}) == session {
fmt.Println("is zero value")
}
구문 분석의 모호성 때문에 if 조건에서 복합 리터럴을 괄호로 묶어야합니다.
==
위 의 사용은 모든 필드가 비교할 수 있는 구조체에 적용됩니다 . 구조체에 비교할 수없는 필드 (슬라이스, 맵 또는 함수)가 포함 된 경우 필드를 0 값과 하나씩 비교해야합니다.
전체 값을 비교하는 대안은 유효한 세션에서 0이 아닌 값으로 설정해야하는 필드를 비교하는 것입니다. 예를 들어 유효한 세션에서 플레이어 ID가! = “”여야하는 경우
if session.playerId == "" {
fmt.Println("is zero value")
}
답변
다음은 3 가지 추가 제안 또는 기술입니다.
추가 필드 포함
추가 필드를 추가하여 구조체가 채워 졌는지 또는 비어 있는지 알 수 있습니다. 나는 의도적으로 이름 ready
이 아닌 empty
a의 영점이 있기 때문 bool
입니다 false
, 당신이 만들 그렇다면 같은 새로운 구조체 Session{}
의 ready
필드가 자동으로 될 것입니다 false
그리고 당신에게 진실을 말할 것이다 : 구조체가 없습니다 아직 (비어의) 준비가되어 있음.
type Session struct {
ready bool
playerId string
beehive string
timestamp time.Time
}
구조체를 초기화 할 때로 설정 ready
해야 true
합니다. 당신의 isEmpty()
당신은 단지 테스트 할 수 있기 때문에 (당신이 원하는 경우에 당신이 하나를 만들 수 있지만) 방법은 더 이상 필요하지 않은 ready
필드 자체를.
var s Session
if !s.ready {
// do stuff (populate s)
}
bool
구조체가 커지거나 비교할 수없는 필드 (예 : 슬라이스 map
및 함수 값) 가 포함 된 경우이 하나의 추가 필드의 중요성이 증가 합니다.
기존 필드의 0 값 사용
이는 이전 제안과 유사하지만 구조체가 비어 있지 않을 때 유효하지 않은 것으로 간주되는 기존 필드의 0 값을 사용합니다 . 이것의 유용성은 구현에 따라 다릅니다.
예를 들어 귀하의 예제 playerId
에서 비어 string
""
있을 수 없다면 다음과 같이 구조체가 비어 있는지 테스트하는 데 사용할 수 있습니다.
var s Session
if s.playerId == "" {
// do stuff (populate s, give proper value to playerId)
}
이 isEmpty()
경우이 검사는 구현에 따라 다르기 때문에이 검사를 메서드에 통합하는 것이 좋습니다.
func (s Session) isEmpty() bool {
return s.playerId == ""
}
그리고 그것을 사용 :
if s.isEmpty() {
// do stuff (populate s, give proper value to playerId)
}
구조체에 포인터 사용
두 번째 제안은 구조체에 대한 포인터를 사용하는 것입니다 : *Session
. 포인터는 nil
값 을 가질 수 있으므로 테스트 할 수 있습니다.
var s *Session
if s == nil {
s = new(Session)
// do stuff (populate s)
}
답변
reflect.deepEqual 을 사용하면 특히 구조체 내부에 맵이있는 경우 에도 작동합니다 .
package main
import "fmt"
import "time"
import "reflect"
type Session struct {
playerId string
beehive string
timestamp time.Time
}
func (s Session) IsEmpty() bool {
return reflect.DeepEqual(s,Session{})
}
func main() {
x := Session{}
if x.IsEmpty() {
fmt.Print("is empty")
}
}
답변
구조체에 대한 포인터를 사용하면 변수를 역 참조하고 빈 구조체에 대한 포인터와 비교하지 않아야합니다.
session := &Session{}
if (Session{}) == *session {
fmt.Println("session is empty")
}
이 놀이터를 확인하십시오 .
또한 여기에서 포인터 조각 인 속성을 보유한 구조체는 동일한 방식으로 비교할 수 없음을 알 수 있습니다.
답변
다른 답변에 대한 대안으로, case
대신 문을 통해 수행하는 경우 원래 의도 한 방식과 유사한 구문 으로이 작업을 수행 할 수 있습니다 if
.
session := Session{}
switch {
case Session{} == session:
fmt.Println("zero")
default:
fmt.Println("not zero")
}
답변
오늘 같은 문제를 다루었 기 때문에 간단히 추가했습니다.
Go 1.13에서는 새로운 isZero()
방법 을 사용할 수 있습니다 .
if reflect.ValueOf(session).IsZero() {
// do stuff...
}
성능과 관련하여 이것을 테스트하지는 않았지만 비교하는 것보다 빠르다고 생각합니다 reflect.DeepEqual()
.
답변
같은 아마 뭔가 이
package main
import "fmt"
import "time"
type Session struct {
playerId string
beehive string
timestamp time.Time
}
func (s Session) Equal(o Session) bool {
if(s.playerId != o.playerId) { return false }
if(s.beehive != o.beehive) { return false }
if(s.timestamp != o.timestamp) { return false }
return true
}
func (s Session) IsEmpty() bool {
return s.Equal(Session{})
}
func main() {
x := Session{}
if x.IsEmpty() {
fmt.Print("is empty")
}
}