¿Cómo comprobar si hay una estructura vacía?
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?
Puede usar == para comparar con un literal compuesto de valor cero porque todos los campos Session
son 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")
}
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 ready
y no empty
porque el valor cero de a bool
sea false
, por lo que si crea una nueva estructura, Session{}
su ready
campo será automático false
y 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 ready
en true
. Su isEmpty()
método ya no es necesario (aunque puede crear uno si lo desea) porque puede probar el ready
campo en sí.
var s Session
if !s.ready {
// do stuff (populate s)
}
La importancia de este campo adicional bool
aumenta a medida que la estructura crece o si contiene campos que no son comparables (por ejemplo, map
valores 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 playerId
no 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 nil
valores, por lo que puedes probarlos:
var s *Session
if s == nil {
s = new(Session)
// do stuff (populate s)
}
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()
.
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")
}
}