Hoe vervelende fout “verklaard en niet gebruikt” te voorkomen

Ik ben Go aan het leren, maar ik vind het een beetje vervelend dat ik bij het compileren geen enkele variabele of pakket ongebruikt mag laten.

Dit vertraagt ​​me echt behoorlijk. Ik wilde bijvoorbeeld gewoon een nieuw pakket declareren en van plan zijn het later te gebruiken of gewoon een commando verwijderen om te testen. Ik krijg altijd de foutmelding en moet al die toepassingen becommentariëren.

Is er een manier om dit soort check in Go te vermijden?


Antwoord 1, autoriteit 100%

Die fout is hier om je te dwingen betere code te schrijven en ervoor te zorgen dat je alles gebruikt wat je declareert of importeert. Het maakt het gemakkelijker om code te lezen die door andere mensen is geschreven (u bent er altijd zeker van dat alle gedeclareerde variabelen zullen worden gebruikt) en voorkomt mogelijke dode code.

Maar als u deze fout echt wilt overslaan, kunt u de lege id(_) :

package main
import (
    "fmt" // imported and not used: "fmt"
)
func main() {
    i := 1 // i declared and not used
}

wordt

package main
import (
    _ "fmt" // no more error
)
func main() {
    i := 1 // no more error
    _ = i
}

Zoals kostix in de reacties hieronder heeft gezegd, kun je het officiële standpunt van het Go-team in de FAQ vinden :

De aanwezigheid van een ongebruikte variabele kan duiden op een bug, terwijl ongebruikte imports de compilatie alleen maar vertragen. Verzamel genoeg ongebruikte imports in je codeboom en het kan erg traag worden. Om deze redenen staat Go geen van beide toe.


Antwoord 2, autoriteit 14%

U kunt hiervoor een eenvoudige “null-functie” gebruiken, bijvoorbeeld:

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

Die je zo kunt gebruiken:

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

Er is ook een pakket hiervoorzodat u de Usefunctie elke keer:

import (
  "github.com/lunux2008/xulu"
)
func main() {
  // [..]
  xulu.Use(a, b, c)
}

Antwoord 3, autoriteit 12%

Volgens de veelgestelde vragen:

Sommigen hebben gevraagd om een ​​compileroptie om deze controles uit te schakelen of ze op zijn minst te reduceren tot waarschuwingen. Een dergelijke optie is echter niet toegevoegd, omdat compileropties de semantiek van de taal niet mogen beïnvloeden en omdat de Go-compiler geen waarschuwingen rapporteert, alleen fouten die compilatie verhinderen.

Er zijn twee redenen waarom er geen waarschuwingen zijn. Ten eerste, als het de moeite waard is om over te klagen, is het de moeite waard om het in de code op te lossen. (En als het niet de moeite waard is om het te repareren, is het ook niet het vermelden waard.) Ten tweede, als de compiler waarschuwingen genereert, wordt de implementatie aangemoedigd om te waarschuwen voor zwakke gevallen die de compilatie luidruchtig kunnen maken, waardoor echte fouten worden gemaskeerd die moeten worden verholpen.

Ik ben het hier niet per se mee eens om verschillende redenen die niet de moeite waard zijn om op in te gaan. Het is wat het is en het is niet waarschijnlijk dat dit in de nabije toekomst zal veranderen.

Voor pakketten is er de goimportstool die automatisch ontbrekende pakketten toevoegt en ongebruikte pakketten verwijdert. Bijvoorbeeld:

# Install it
$ go get golang.org/x/tools/cmd/goimports
# -w to write the source file instead of stdout
$ goimports -w my_file.go

Je zou dit vanuit elke fatsoenlijke editor moeten kunnen uitvoeren, bijvoorbeeld voor Vim:

:!goimports -w %

De pagina goimportsbevat enkele opdrachten voor andere editors, en u stelt deze meestal in om automatisch te worden uitgevoerd wanneer u de buffer op schijf opslaat.

Houd er rekening mee dat goimportsook gofmtzal uitvoeren.


Zoals reeds vermeld, is de eenvoudigste manier voor variabelen om ze (tijdelijk) toe te wijzen aan _:

// No errors
tasty := "ice cream"
horrible := "marmite"
// Commented out for debugging
//eat(tasty, horrible)
_, _ = tasty, horrible

Antwoord 4, autoriteit 7%

Ik kwam dit tegen toen ik Go 2 jaar geleden leerde, dus ik heb mijn eigen functie aangegeven.

// UNUSED allows unused variables to be included in Go programs
func UNUSED(x ...interface{}) {}

En dan kun je het zo gebruiken:

UNUSED(x)
UNUSED(x, y)
UNUSED(x, y, z)

Het mooie is dat je alles kunt doorgeven aan UNUSED.

Is het beter dan het volgende?

_, _, _ = x, y, z

Dat is aan jou.


Antwoord 5, autoriteit 4%

Als anderen het moeilijk vinden om dit te begrijpen, denk ik dat het zou kunnen helpen om het in heel duidelijke bewoordingen uit te leggen. Als je een variabele hebt die je niet gebruikt, bijvoorbeeld een functie waarvoor je de aanroep hebt weggelaten (een veelvoorkomende use-case):

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

U kunt een nutteloze/lege variabele aan de functie toewijzen, zodat deze niet langer ongebruiktis:

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

Antwoord 6, autoriteit 3%

Een hoek die tot nu toe nog niet is genoemd, zijn toolsets die worden gebruikt voor het bewerken van de code.

Gebruik Visual Studio Codesamen met de extensie van lukehobangenaamd Gozal wat automagie voor je doen. De Go-extensie voert automatisch gofmt, golintenz. uit, en verwijdert en voegt import-itemstoe. Dus dat deel is nu in ieder geval automatisch.

Ik geef toe dat het niet 100% de oplossing voor de vraag is, maar hoe nuttig genoeg ook.


Antwoord 7, autoriteit 2%

Voor zover ik weet, deze regelsin de Go-compiler zien eruit als de regels die moeten worden verwijderd. Je zou in staat moeten zijn om je eigen toolchain te bouwen die deze contraproductieve waarschuwingen negeert.


Antwoord 8

Ik kwam dit probleem tegen toen ik het verzenden van een e-mail tijdelijk wilde uitschakelen terwijl ik aan een ander deel van de code werkte.

Commentaar geven op het gebruik van de service veroorzaakte veel cascadefouten, dus in plaats van commentaar te geven heb ik een voorwaarde gebruikt

if false {
    // Technically, svc still be used so no yelling
    _, err = svc.SendRawEmail(input) 
    Check(err)
}

Other episodes