Jak uniknąć irytującego błędu „zadeklarowany i nieużywany”

238

Uczę się Go, ale wydaje mi się, że to trochę denerwujące, że podczas kompilacji nie powinienem pozostawiać żadnej zmiennej lub pakietu nieużywanych.

To naprawdę mnie spowalnia. Na przykład chciałem tylko zadeklarować nowy pakiet i planować użyć go później lub po prostu odkomentować jakieś polecenie do przetestowania. Zawsze pojawia się błąd i muszę komentować wszystkie te zastosowania.

Czy jest jakiś sposób na uniknięcie tego rodzaju odprawy w Go?

A-letubby
źródło
1
Możesz także użyć goimports ( godoc.org/code.google.com/p/go.tools/cmd/goimports ), aby automatycznie dodać / usunąć import.
elithrar
3
Nadal uważam, że opcja kompilatora byłaby przydatna w przepływie pracy „Chcę coś skomentować, aby ułatwić debugowanie”.
RJFalconer
13
Ta funkcja jest świetnym sposobem na marnowanie czasu lol ludzi, jaki jest sens? Kiedy zatwierdzasz / wysyłasz kod, ok, nieużywane zmienne są fajne, ale przy jego tworzeniu? Okropny.
Alexander Mills,
Jest rok 2020 i nie mogę uwierzyć, że nadal tego nie naprawili (nawet przy użyciu flagi kompilatora). Zrobiłem projekt w Go około 5 lat temu i ogólnie polubiłem ten język, ale był on dla mnie bezużyteczny wyłącznie z tego powodu. Sposób, w jaki koduję, ciągle komentuję / odkomentuję, więc ta „funkcja” w Go sprawia, że ​​wszystko zajmuje mi dwa razy więcej czasu ... Od tego czasu sprawdzam co kilka miesięcy, aby sprawdzić, czy nie wyczułam rozsądku zespół Go i jak dotąd brak szczęścia ... Sucks. W przeciwnym razie jest to świetny język i chciałbym go częściej używać, ale obecnie nie jest on dla mnie przydatny.
Ruslan,

Odpowiedzi:

234

Ten błąd zmusza Cię do napisania lepszego kodu i upewnij się, że używasz wszystkiego, co deklarujesz lub importujesz. Ułatwia to odczytywanie kodu napisanego przez inne osoby (zawsze masz pewność, że zostaną użyte wszystkie zadeklarowane zmienne) i unikniesz możliwego martwego kodu.

Ale jeśli naprawdę chcesz pominąć ten błąd, możesz użyć pustego identyfikatora ( _):

package main

import (
    "fmt" // imported and not used: "fmt"
)

func main() {
    i := 1 // i declared and not used
}

staje się

package main

import (
    _ "fmt" // no more error
)

func main() {
    i := 1 // no more error
    _ = i
}

Jak powiedział kostix w komentarzach poniżej, oficjalne stanowisko zespołu Go można znaleźć w FAQ :

Obecność nieużywanej zmiennej może wskazywać na błąd, podczas gdy nieużywany import spowalnia kompilację. Zbierz wystarczającą liczbę nieużywanych importów w drzewie kodu, a rzeczy mogą stać się bardzo wolne. Z tych powodów Go nie zezwala.

Florent Bayle
źródło
90
Jednak nie różni się to tak bardzo od komentowania tego. Rozumiem, że jest to lepszy kod, ale czy byłoby lepiej, gdybyśmy mogli zamknąć sprawdzian, dlaczego testujemy nasz kod, a następnie ponownie go otworzyć, gdy chcemy zakończyć kod i wyczyścić go?
A-letubby
21
@kostix Cóż ... to może cię nie spowolnić, ponieważ możesz być ekspertem, ale jest to dla mnie i dla mnie sposób, w jaki koduję. Zastanawiam się tylko, czy jest lepszy sposób. Ale i tak dziękuję za FAQ! Czytając to, mogę całkowicie zrozumieć, z jakich powodów golang robi to w ten sposób.
A-letubby
20
Czy istnieje argument wiersza polecenia, aby to wyłączyć? Czy jest to funkcja niezmienna?
Ethan Bierlein
26
FWIW, miałem złe czasy czytając kod innych, ale zdecydowanie nie z powodu nieużywanych symboli. OTOH, straciłem dzisiaj godzinę na badanie metod radzenia sobie z tą * #% $ golang „funkcją”.
Torsten Bronger
24
Niestety ta odpowiedź jest poprawna - ale to nie uzasadnia. Istnieje duża różnica między sprawdzaniem kodu a jego wykonywaniem. Kiedy sprawdzamy kod, używamy kłaczków, aby wychwycić tego rodzaju błąd. Kiedy wykonujemy podczas szybkiego rozwoju, nie mamy takich samych standardów. Niewybaczalne jest mylenie kompilatora z linerem. Nawet policja stylu w Google nie popełnia tego błędu.
Travis Wilson
29

Możesz użyć do tego prostej „funkcji zerowej”, na przykład:

func Use(vals ...interface{}) {
    for _, val := range vals {
        _ = val
    }
}

Którego możesz użyć tak:

package main

func main() {
    a := "declared and not used"
    b := "another declared and not used"
    c := 123

    Use(a, b, c)
}

Jest do tego również pakiet, więc nie musisz za Usekażdym razem definiować funkcji:

import (
  "github.com/lunux2008/xulu"
)

func main() {
  // [..]

  xulu.Use(a, b, c)
}
lunux2008
źródło
29

Zgodnie z FAQ :

Niektórzy poprosili o opcję kompilatora, aby wyłączyć te kontrole lub przynajmniej ograniczyć je do ostrzeżeń. Taka opcja nie została jednak dodana, ponieważ opcje kompilatora nie powinny wpływać na semantykę języka, a ponieważ kompilator Go nie zgłasza ostrzeżeń, tylko błędy uniemożliwiające kompilację.

Istnieją dwa powody braku ostrzeżeń. Po pierwsze, jeśli warto narzekać, warto to naprawić w kodzie. (A jeśli nie warto tego naprawiać, nie warto o tym wspominać.) Po drugie, generowanie ostrzeżeń przez kompilator zachęca implementację do ostrzegania o słabych przypadkach, które mogą powodować hałas w kompilacji, maskując prawdziwe błędy, które należy naprawić.

Niekoniecznie się z tym zgadzam z różnych powodów, w które nie warto wchodzić. Tak właśnie jest i prawdopodobnie nie zmieni się w najbliższej przyszłości.

W przypadku pakietów istnieje goimportsnarzędzie, które automatycznie dodaje brakujące pakiety i usuwa nieużywane. Na przykład:

# Install it
$ go get golang.org/x/tools/cmd/goimports

# -w to write the source file instead of stdout
$ goimports -w my_file.go

Powinieneś być w stanie uruchomić to z dowolnego w połowie przyzwoitego edytora - na przykład dla Vima:

:!goimports -w %

Na goimportsstronie znajduje się lista niektóre polecenia dla innych redaktorów i zazwyczaj ustawić go uruchomić automatycznie po zapisaniu bufora na dysk.

Pamiętaj, że goimportsbędzie również działać gofmt.


Jak już wspomniano, w przypadku zmiennych najłatwiej jest (tymczasowo) przypisać je do _:

// No errors
tasty := "ice cream"
horrible := "marmite"

// Commented out for debugging
//eat(tasty, horrible)

_, _ = tasty, horrible
Martin Tournoij
źródło
9

Jednym z niewymienionych jeszcze kątów są zestawy narzędzi używane do edycji kodu.

Używanie Visual Studio Code wraz z wywoływanym rozszerzeniem od lukehobanGo zrobi dla ciebie auto-magię. Rozszerzenie Go uruchamia się automatycznie gofmt, golintetc, i usuwa i dodaje importwpisy . Więc przynajmniej ta część jest teraz automatyczna.

Przyznaję, że nie jest to w 100% rozwiązanie tego pytania, ale jest wystarczająco użyteczne.

miltonb
źródło
8

W przypadku, gdy innym trudno jest to zrozumieć, myślę, że może to pomóc wyjaśnić to w bardzo prosty sposób. Jeśli masz zmienną, której nie używasz, na przykład funkcję, dla której skomentowałeś wywołanie (częsty przypadek użycia):

myFn := func () { }
// myFn()

Możesz przypisać do funkcji niepotrzebną / pustą zmienną, aby nie była już nieużywana :

myFn := func () { }
_ = myFn
// myFn()
max pleaner
źródło