detección nula en Go
Veo mucho código en Go para detectar nil, así:
if err != nil {
// handle the error
}
Sin embargo, tengo una estructura como esta:
type Config struct {
host string
port float64
}
Y config es una instancia de Config, cuando lo hago:
if config == nil {
}
Hay un error de compilación, diciendo: no se puede convertir nil a type Config
5 answers
El compilador está apuntando el error a usted, usted está comparando una instancia de estructura y nil. No son del mismo tipo, así que lo considera una comparación inválida y te grita.
Lo que quiere hacer aquí es comparar un puntero a su instancia de configuración con nil, que es una comparación válida. Para hacer eso, puede usar el golang nuevo incorporado, o inicializar un puntero a él:
config := new(Config) // not nil
O
config := &Config{host: myhost.com, port: 22} // not nil
O
var config *Config // nil
Entonces usted será capaz de comprobar si
if config == nil {
// then
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-22 01:42:32
Además de Oleiade, ver la especificación sobre valores cero :
Cuando se asigna memoria para almacenar un valor, ya sea a través de una declaración o una llamada de make o new, y no se proporciona una inicialización explícita, la memoria recibe una inicialización predeterminada. Cada elemento de tal valor se establece en el valor cero para su tipo: false para booleanos, 0 para enteros, 0.0 para flotadores, "" para cadenas, y nil para punteros, funciones, interfaces, sectores, canales y mapas. Esta inicialización se realiza recursivamente, por lo que, por ejemplo, cada elemento de una matriz de estructuras tendrá sus campos a cero si no se especifica ningún valor.
Como puede ver, nil
no es el valor cero para cada tipo, sino solo para punteros, funciones, interfaces, sectores, canales y mapas. Esta es la razón por la que config == nil
es un error y
&config == nil
no lo es.
Para verificar si su estructura no está inicializada, tendría que verificar que cada miembro
valor cero respectivo (por ejemplo, host == ""
, port == 0
, sucesivamente.) o tener un campo privado que
se establece mediante un método de inicialización interna. Ejemplo:
type Config struct {
Host string
Port float64
setup bool
}
func NewConfig(host string, port float64) *Config {
return &Config{host, port, true}
}
func (c *Config) Initialized() bool { return c != nil && c.setup }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-06 15:18:11
He creado algunos algunos código de ejemplo que crea una nueva variable utilizando una variedad de maneras que puedo pensar. Parece que las primeras 3 formas crean valores, y las dos últimas crean referencias.
package main
import "fmt"
type Config struct {
host string
port float64
}
func main() {
//value
var c1 Config
c2 := Config{}
c3 := *new(Config)
//reference
c4 := &Config{}
c5 := new(Config)
fmt.Println(&c1 == nil)
fmt.Println(&c2 == nil)
fmt.Println(&c3 == nil)
fmt.Println(c4 == nil)
fmt.Println(c5 == nil)
fmt.Println(c1, c2, c3, c4, c5)
}
Que produce:
false
false
false
false
false
{ 0} { 0} { 0} &{ 0} &{ 0}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-28 17:53:46
También puedes marcar como struct_var == (struct{})
. Esto no le permite comparar con nil, pero comprueba si está inicializado o no. Tenga cuidado al usar este método. Si su estructura puede tener valores cero para todos sus campos, no tendrá un gran tiempo.
package main
import "fmt"
type A struct {
Name string
}
func main() {
a := A{"Hello"}
var b A
if a == (A{}) {
fmt.Println("A is empty") // Does not print
}
if b == (A{}) {
fmt.Println("B is empty") // Prints
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-22 02:02:21
La especificación del lenguaje menciona los comportamientos de los operadores de comparación:
En cualquier comparación, el primer operando debe ser asignable al tipo del segundo operando, o viceversa.
Un valor x es asignable a una variable de tipo T ("x es asignable a T") en cualquiera de estos casos:
- el tipo de x es idéntico a T.
- tipo V y T de X tienen tipos subyacentes idénticos y al menos uno de V o T no es un tipo con nombre.
- T es un tipo de interfaz y x implementa T.
- x es un valor de canal bidireccional, T es un tipo de canal, el tipo de X V y T tienen tipos de elementos idénticos, y al menos uno de V o T no es un tipo con nombre.
- x es el identificador predeclarado nil y T es un puntero, función, segmento, mapa, canal o tipo de interfaz.
- x es una constante sin tipo representable por un valor de tipo T.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-12 08:07:31