为什么Go认为我没有使用声明的变量?

I am new to Go and wondering why does Go think I am not using vpcGrp? How would you code this?

Here is my code:

var vpcGrp *ec2.SecurityGroup
grpExists := false
resp, err := svc.DescribeSecurityGroups(params)
if err != nil {
    log.Error(err)
} else {
    for _, v := range resp.SecurityGroups {
        if *v.GroupName == grpName {
            log.Debug("VPC Security Group Found [", grpName, "]")
            vpcGrp = v
            grpExists = true
        }
    }
}

if !grpExists {
    vpcGrp, err := createDbSecurityGrp(grpName, vpcId, region)
    if err != nil {
        log.Error(err)
        return nil, err
    }
}

return vpcGrp, nil

The Go Programming Language Specification

Blocks

A block is a possibly empty sequence of declarations and statements within matching brace brackets.

Block = "{" StatementList "}" .
StatementList = { Statement ";" } .

In addition to explicit blocks in the source code, there are implicit blocks:

  • The universe block encompasses all Go source text.

  • Each package has a package block containing all Go source text for that package.

  • Each file has a file block containing all Go source text in that file.

  • Each "if", "for", and "switch" statement is considered to be in its own implicit block.

  • Each clause in a "switch" or "select" statement acts as an implicit block.

Blocks nest and influence scoping.

Declarations and scope

A declaration binds a non-blank identifier to a constant, type, variable, function, label, or package. Every identifier in a program must be declared. No identifier may be declared twice in the same block, and no identifier may be declared in both the file and package block.

The blank identifier may be used like any other identifier in a declaration, but it does not introduce a binding and thus is not declared. In the package block, the identifier init may only be used for init function declarations, and like the blank identifier it does not introduce a new binding.

Declaration   = ConstDecl | TypeDecl | VarDecl .
TopLevelDecl  = Declaration | FunctionDecl | MethodDecl .

The scope of a declared identifier is the extent of source text in which the identifier denotes the specified constant, type, variable, function, label, or package.

Go is lexically scoped using blocks:

  • The scope of a predeclared identifier is the universe block.
  • The scope of an identifier denoting a constant, type, variable, or function (but not method) declared at top level (outside any function) is the package block.
  • The scope of the package name of an imported package is the file block of the file containing the import declaration.
  • The scope of an identifier denoting a method receiver, function parameter, or result variable is the function body.
  • The scope of a constant or variable identifier declared inside a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl for short variable declarations) and ends at the end of the innermost containing block.
  • The scope of a type identifier declared inside a function begins at the identifier in the TypeSpec and ends at the end of the innermost containing block.

An identifier declared in a block may be redeclared in an inner block. While the identifier of the inner declaration is in scope, it denotes the entity declared by the inner declaration.

Short variable declarations

A short variable declaration uses the syntax:

ShortVarDecl = IdentifierList ":=" ExpressionList .

It is shorthand for a regular variable declaration with initializer expressions but no types:

"var" IdentifierList = ExpressionList .

Short variable declarations may appear only inside functions. In some contexts such as the initializers for "if", "for", or "switch" statements, they can be used to declare local temporary variables.

Each "if", "for", and "switch" statement is considered to be in its own implicit block.

An identifier declared in a block may be redeclared in an inner block. While the identifier of the inner declaration is in scope, it denotes the entity declared by the inner declaration.

In some contexts such as the initializers for "if", "for", or "switch" statements, short variable declarations can be used to declare local temporary variables.

if !grpExists {
    vpcGrp, err := createDbSecurityGrp(grpName, vpcId, region)
    if err != nil {
        log.Error(err)
        return nil, err
    }
}

vpcGrp is a local variable that is set but not read; it's not used. err is a local variable that is both set and read; it's used.

Since vpcGrp and err have already been declared in an outer scope, try

 vpcGrp, err = createDbSecurityGrp(grpName, vpcId, region)