Go中的变量初始化

huangapple go评论151阅读模式
英文:

Variable init in Go

问题

我看到以下的代码(我稍微简化了一下)。

func getEndpoints(db *sqlx.DB) s.Endpoints {
    var endpoints s.Endpoints
    {
        repository := acl.NewRepository(db)
        service := stat.NewService(repository)
        endpoints = s.Endpoints{
            GetEndpoint: s.MakeEndpoint(service),
        }
    }

    return endpoints
}

如果我正确理解这段代码,var endpoints s.Endpoints{...}内部的代码是逐行执行的,而endpoints = s.Endpoints ...这一行初始化了上面声明的var endpoints变量。

我认为将其重写为以下形式是正确的(如果我理解错了,请纠正我):

func getEndpoints(db *sqlx.DB) s.Endpoints {
    repository := acl.NewRepository(db)
    service := stat.NewService(repository)
    endpoints := s.Endpoints{
        GetEndpoint: s.MakeEndpoint(service),
    }

    return endpoints
}

那么,有人可以解释一下为什么初始化写在var endpoints s.Endpoints{...}内部吗?这样做有什么想法吗?我是否漏掉了什么?

英文:

I see following code (I simplified it a bit).

func getEndpoints(db *sqlx.DB) s.Endpoints {
    var endpoints s.Endpoints
    {
	    repository := acl.NewRepository(db)
	    service := stat.NewService(repository)
	    endpoints = s.Endpoints{
		    GetEndpoint: s.MakeEndpoint(service),
	    }
    }

	return endpoints 
}

If I understand this code correctly, code inside var endpoints s.Endpoints{...} is executed line by line and endpoints = s.Endpoints ... line initialises var endpoints variable declared above.

I suppose that it's correct to rewrite it like this (correct me if I'm wrong):

func getEndpoints(db *sqlx.DB) s.Endpoints {
   
	repository := acl.NewRepository(db)
	service := stat.NewService(repository)
	endpoints := s.Endpoints{
		GetEndpoint: s.MakeEndpoint(service),
	}
   
	return endpoints 
}

So can somebody explain me why initialisation is written inside var endpoints s.Endpoints{...}. Is there any idea to do it like this? Am I missing something?

答案1

得分: 3

它们是等价的。

{...} 块与使用 var 关键字进行变量声明没有任何关系。它们只是恰好连续写在一起。

{...} 只是一个简单的,没有其他含义。var 声明不需要该块,即使有一个块存在,它也与变量声明无关。你可以在任何可以插入语句的地方插入一个块。

当需要使用显式块的罕见情况(当不需要时)是为了分组语句,并控制在其中声明的变量和其他标识符的作用域,因为变量的作用域在最内层包含块的末尾结束(规范:声明和作用域)。

英文:

They are equivalent.

The {...} block has nothing to do with the variable declaration with the var keyword. It just happens to be written one after the other.

The {...} is a simple block, nothing else. The var declaration does not require that block, and even if there is one, it is not related to the variable declaration. You can insert a block wherever you would insert a statement.

The rare case when an explicit block is used (when there isn't required one) is to group statements, and to control the scope of the variables and other identifiers declared inside them, because the scope of the variables end at the end of the innermost containing block (Spec: Declarations and Scope).

答案2

得分: 3

添加一个新的代码块将创建一个新的变量作用域,该代码块中声明的变量在其外部将不可用:

var endpoints s.Endpoints
{
    repository := acl.NewRepository(db)
    service := stat.NewService(repository)
    endpoints = s.Endpoints{
        GetEndpoint: s.MakeEndpoint(service),
    }
}

// 这里无法访问 service 和 repository 变量!

在你的具体简化示例中这样做可能没有太多意义但如果你有其他具有相同变量的代码块这样做就更有意义例如

```go
var endpoints s.Endpoints
{
    repository := acl.NewRepository(db)
    service := stat.NewService(repository)
    endpoints = s.Endpoints{
        GetEndpoint: s.MakeEndpoint(service),
    }
}

// 获取另一个 repository
{
    repository := otherRepo.NewRepository(db)
    repository.DoSomething()
}

有些人认为这是一种"良好的编程习惯"。个人而言,我认为这样做会降低可读性,不值得这样做。

英文:

Adding a new block will create a new variable scope, and variables declared in that block will not be available outside of it:

var endpoints s.Endpoints
{
    repository := acl.NewRepository(db)
    service := stat.NewService(repository)
    endpoints = s.Endpoints{
        GetEndpoint: s.MakeEndpoint(service),
    }
}

// service and repository  variables are not defined here!

In your specific simplified example it makes little sense, but if you have other blocks with the same variables it makes more sense. For example:

var endpoints s.Endpoints
{
    repository := acl.NewRepository(db)
    service := stat.NewService(repository)
    endpoints = s.Endpoints{
        GetEndpoint: s.MakeEndpoint(service),
    }
}

 // Get another repository
{
    repository := otherRepo.NewRepository(db)
    repository.DoSomething()
}

Some people consider this "good hygiene". Personally, I don't think it's worth the decrease in readability.

huangapple
  • 本文由 发表于 2017年7月4日 14:51:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/44898833.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定