wykrywanie zerowe w Go

Widzę dużo kodu W Go, aby wykryć nil, jak to:

if err != nil { 
    // handle the error    
}

Jednak mam taką strukturę:

type Config struct {
    host string  
    port float64
}

A config jest instancją Config, gdy robię:

if config == nil {
}

Jest błąd kompilacji, mówiący: nie można przekonwertować nil do typu Config

 106
Author: John Weldon, 2013-11-27

5 answers

Kompilator wskazuje Ci błąd, porównujesz instancję struktury i nil. Nie są tego samego typu, więc uważa to za nieprawidłowe porównanie i krzyczy na Ciebie.

To, co chcesz tutaj zrobić, to porównać wskaźnik do instancji config do nil, co jest poprawnym porównaniem. Aby to zrobić, możesz użyć wbudowanego golang new lub zainicjalizować wskaźnik do niego:

config := new(Config) // not nil

Lub

config := &Config{host: myhost.com, port: 22} // not nil

Lub

var config *Config // nil

Wtedy będziesz mógł sprawdzić, czy

if config == nil {
    // then
}
 129
Author: Oleiade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-22 01:42:32

Oprócz Oleiade, zobacz spec na wartościach zerowych :

Gdy pamięć jest przydzielona do przechowywania wartości, poprzez deklarację lub wywołanie make lub new i nie jest zapewniona Jawna inicjalizacja, pamięć otrzymuje domyślną inicjalizację. każdy element takiej wartości jest ustawiony na wartość zero dla swojego typu: false Dla wartości logicznych, 0 dla liczb całkowitych, 0.0 dla pływaków, "" dla łańcuchów i nil Dla wskaźników, funkcji, interfejsów, plastrów, kanałów i map. Ta inicjalizacja jest wykonywana rekurencyjnie, więc na przykład każdy element tablicy struktur będzie miał swoje pola zerowane, jeśli nie zostanie podana żadna wartość.

Jak widać, nil nie jest wartością zerową dla każdego typu, ale tylko dla wskaźników, funkcji, interfejsów, plastrów, kanałów i map. Z tego powodu {[2] } jest błędem i Nie jest.

Aby sprawdzić, czy Twoja struktura jest niezinicjalizowana, musisz sprawdzić każdy członek pod kątem jej odpowiednia wartość zerowa (np. host == "", port == 0, itd.) lub mieć prywatne pole, które jest ustawiany przez wewnętrzną metodę inicjalizacji. Przykład:

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 }
 50
Author: nemo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-06 15:18:11

Stworzyłem przykładowy kod, który tworzy nową zmienną na różne sposoby, które mogę wymyślić. Wygląda na to, że pierwsze 3 sposoby tworzą wartości, a dwa ostatnie tworzą referencje.

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)
}

Które Wyjście:

false
false
false
false
false
{ 0} { 0} { 0} &{ 0} &{ 0}
 14
Author: Elgs Qian Chen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-28 17:53:46

Możesz również sprawdzić jak struct_var == (struct{}). Nie pozwala to na porównanie z nil, ale sprawdza, czy jest zainicjowany, czy nie. Należy zachować ostrożność podczas stosowania tej metody. Jeśli twoja struktura może mieć zero wartości dla wszystkich swoich pól, nie będziesz miał czasu.

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
    } 
}

Http://play.golang.org/p/RXcE06chxE

 5
Author: Thellimist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-22 02:02:21

Spec języka wymienia zachowania operatorów porównawczych:

Operatory porównania

W każdym porównaniu, pierwszy operand musi być przypisany do typu drugiego operandu lub odwrotnie.


Przypisanie

Wartość x można przypisać do zmiennej typu T ("X można przypisać do T") w każdym z tych przypadków:

  • typ x jest identyczny z T.
  • x Typu V i T mają identyczne typy bazowe i co najmniej jeden z V lub T nie jest typem nazwanym.
  • T jest typem interfejsu, a X implementuje T.
  • x jest dwukierunkową wartością kanału, T jest typem kanału, x Typu V i T mają identyczne typy elementów, a przynajmniej jeden z V lub T nie jest Typ nazwany.
  • x jest identyfikatorem zerowym, A T jest wskaźnikiem, funkcją, wycinkiem, mapą, kanałem lub typem interfejsu.
  • x jest niestandardową stałą reprezentowaną przez wartość typu T.
 3
Author: supei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 08:07:31