¿Cómo comprobar si hay una estructura vacía?

Resuelto Michael asked hace 9 años • 8 respuestas

Defino una estructura...

type Session struct {
    playerId string
    beehive string
    timestamp time.Time
}

A veces le asigno una sesión vacía (porque nil no es posible)

session = Session{};

Entonces quiero comprobar si está vacío:

if session == Session{} {
     // do stuff...
}

Obviamente esto no está funcionando. ¿Cómo lo escribo?

Michael avatar Feb 11 '15 12:02 Michael
Aceptado

Puede usar == para comparar con un literal compuesto de valor cero porque todos los campos Sessionson comparables :

if (Session{}) == session  {
    fmt.Println("is zero value")
}

ejemplo de patio de recreo

Debido a una ambigüedad en el análisis , se requieren paréntesis alrededor del literal compuesto en la condición if.

El uso de lo ==anterior se aplica a estructuras donde todos los campos son comparables . Si la estructura contiene un campo no comparable (sección, mapa o función), entonces los campos deben compararse uno por uno con sus valores cero.

Una alternativa a comparar el valor completo es comparar un campo que debe establecerse en un valor distinto de cero en una sesión válida. Por ejemplo, si la identificación del jugador debe ser != "" en una sesión válida, use

if session.playerId == "" {
    fmt.Println("is zero value")
}
Cerise Limón avatar Feb 11 '2015 05:02 Cerise Limón

Aquí hay 3 sugerencias o técnicas más:

Con un campo adicional

Puede agregar un campo adicional para saber si la estructura se ha completado o está vacía. Lo nombré intencionalmente readyy no emptyporque el valor cero de a boolsea false, por lo que si crea una nueva estructura, Session{}su readycampo será automático falsey le dirá la verdad: que la estructura aún no está lista (está vacía).

type Session struct {
    ready bool

    playerId string
    beehive string
    timestamp time.Time
}

Cuando inicializas la estructura, debes configurarla readyen true. Su isEmpty()método ya no es necesario (aunque puede crear uno si lo desea) porque puede probar el readycampo en sí.

var s Session

if !s.ready {
    // do stuff (populate s)
}

La importancia de este campo adicional boolaumenta a medida que la estructura crece o si contiene campos que no son comparables (por ejemplo, mapvalores de división y función).

Usar el valor cero de un campo existente

Esto es similar a la sugerencia anterior, pero utiliza el valor cero de un campo existente que se considera no válido cuando la estructura no está vacía. La usabilidad de esto depende de la implementación.

Por ejemplo, si en su ejemplo playerIdno puede estar vacío string "", puede usarlo para probar si su estructura está vacía de esta manera:

var s Session

if s.playerId == "" {
    // do stuff (populate s, give proper value to playerId)
}

En este caso, vale la pena incorporar esta verificación en un isEmpty()método porque esta verificación depende de la implementación:

func (s Session) isEmpty() bool {
    return s.playerId == ""
}

Y usándolo:

if s.isEmpty() {
    // do stuff (populate s, give proper value to playerId)
}

Utilice puntero a su estructura

La segunda sugerencia es utilizar un puntero a su estructura: *Session. Los punteros pueden tener nilvalores, por lo que puedes probarlos:

var s *Session

if s == nil {
    s = new(Session)
    // do stuff (populate s)
}
icza avatar Feb 11 '2015 08:02 icza

Solo una adición rápida, porque hoy abordé el mismo problema:

Con Go 1.13 es posible utilizar el nuevo isZero()método:

if reflect.ValueOf(session).IsZero() {
     // do stuff...
}

No probé esto con respecto al rendimiento, pero supongo que debería ser más rápido que comparar a través de reflect.DeepEqual().

Shibumi avatar Aug 06 '2020 17:08 Shibumi

Usar reflect.deepEqual también funciona , especialmente cuando tienes un mapa dentro de la estructura

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")
  } 
}
Kokizzu avatar Feb 11 '2015 05:02 Kokizzu