本节将随着时间的推移而增长,但主要目标是分享一些有经验的开发人员在一段时间内发现的技巧。希望这些技巧能让新用户更快地提高工作效率。

Go 语言入门很简单--技巧和窍门(Tips and Tricks)_golang

140个字符提示

[宇宙之一粟翻译]:

  • leave your object oriented brain at home. Embrace the interface. ​​@mikegehard​

别想着面向对象了,拥抱接口吧。

  • Learn to do things the Go way, don’t try to force your language idioms into Go. ​​@DrNic​

学习用 Go 语言的方式做事,不要试图把你的语言习性强加给Go。

  • It’s better to over do it with using interfaces than use too few of them. ​​@evanphx​

接口使用宜多不宜少。

  • Embrace the language: simplicity, concurrency, and composition. ​​@francesc​

拥抱这门语言:简单、并发和组合。

阅读他们在golang.org网站上的所有精彩文档。

多多使用 ​​gofmt​​ 

阅读大量的源码。

  • Learn and become familiar with tools and utilities, or create your own! They are as vital to your success as knowing the language. ​​@coreyprak​

学习并熟悉工具和实用程序,或创建自己的工具和实用程序!它们对您的成功与了解语言一样重要

额外导入包的方法

还有其他几种导入包的方法。我们将在以下示例中使用 fmt 包:

  • ​import format "fmt"​​ : 创建 ​​fmt​​ 的别名. 然后在所有使用 ​​fmt​​ 包内容的地方使用 ​​format.​​ 而不是 ​​fmt.​​如 ​​format.Println("Hello,World")​​ 。
  • ​import . "fmt"​​​ : 多了个点号 ​​.​​​ ,这种方式​允许直接访问包的内容,无需在其前面加上 ​​fmt​​ 。
  • ​import _ "fmt"​​​ - 如果未使用 ​​fmt​​​ ,则抑制与 ​​fmt​​​  相关的编译器警告,如果有则执行初始化函数。 ​​fmt​​  的其余部分无法访问。

有关更多详细信息,请参阅​​此博客​​文章。

​goimports​

​Goimports​​ 是一种更新 Go 导入行、添加缺失行和删除未引用行的工具。

它的作用与 gofmt(插入式替换)相同,但除了代码格式之外,还修复了导入。

代码组织

Go是一种非常简单的编程语言,但首先是开发人员最难的事情是如何组织代码。由于许多原因,轨道变得流行,并且脚手架是其中之一。它给出了新的开发人员清晰的指示和地方,以便将其代码和成语遵循。

在某种程度上,Go 通过为开发人员提供很棒的工具(如 go fmt)以及不会编译未使用的变量或未使用的导入语句的严格编译器来做同样的事情。

自定义构造函数

我经常听到的一个问题是我应该什么时候使用像 ​​NewJob​​  这样的自定义构造函数。我的答案是,在大多数情况下你不需要。但是,每当您需要在初始化时间设置值并且您有某种默认值时,它都是构造函数的好候选者。在上面的示例中,添加构造函数会产生很多意义,因此我们可以设置默认记录器。

package main

import (
"log"
"os"
)

type Job struct {
Command string
*log.Logger
}

func NewJob(command string) *Job {
return &Job{command, log.New(os.Stderr, "Job: ", log.Ldate)}
}

func main() {
NewJob("demo").Print("starting now...")
}

重构包中的代码

参见这篇关于​​重构 Go 代码​​的博客文章,第一部分讨论包组织。

集合

您可能希望找到一种方法来从集合中提取唯一值。用其他语言,您通常具有不允许重复的集数据结构。Go 没有内置的,但它不太难以实现(由于缺乏泛型,你需要为大多数类型做到这一点,这可能是麻烦的)。

// UniqStr returns a copy if the passed slice with only unique string results.
func UniqStr(col []string) []string {
m := map[string]struct{}{}
for _, v := range col {
if _, ok := m[v]; !ok {
m[v] = struct{}{}
}
}
list := make([]string, len(m))

i := 0
for v := range m {
list[i] = v
i++
}
return list
}

我使用了一些有趣的技巧。首先,空结构体的映射:

  m := map[string]struct{}{}

我们创建了一个映射,键是我们想要唯一的值,关联的值并不重要,所以它可以是任何东西。例如:

m := map[string]bool{}

然而,我选择了一个空结构,因为它会像布尔值一样快,但不会分配那么多内存。

第二个技巧可以看得更清楚一点:

if _, ok := m[v]; !ok {
m[v] = struct{}{}
}

我们在这里所做的,只是检查映射 m 中是否有与键 v 关联的值,我们不关心值本身,但是如果我们知道我们没有值,那么我们添加一个。

一旦我们有了一个带有唯一键的映射,我们就可以将它们提取到一个新的字符串切片中并返回结果。

下面是这个函数的测试,如你所见,我使用了一个表测试,这是运行单元测试的惯用 Go 方式:

func TestUniqStr(t *testing.T) {

data := []struct{ in, out []string }{
{[]string{}, []string{}},
{[]string{"", "", ""}, []string{""}},
{[]string{"a", "a"}, []string{"a"}},
{[]string{"a", "b", "a"}, []string{"a", "b"}},
{[]string{"a", "b", "a", "b"}, []string{"a", "b"}},
{[]string{"a", "b", "b", "a", "b"}, []string{"a", "b"}},
{[]string{"a", "a", "b", "b", "a", "b"}, []string{"a", "b"}},
{[]string{"a", "b", "c", "a", "b", "c"}, []string{"a", "b", "c"}},
}

for _, exp := range data {
res := UniqStr(exp.in)
if !reflect.DeepEqual(res, exp.out) {
t.Fatalf("%q didn't match %q\n", res, exp.out)
}
}

}

依赖包管理

不幸的是,Go 没有自带依赖包管理系统。可能是因为它起源于 C 文化,包没有版本化,也没有解决显式的版本依赖问题。

挑战是,如果您的项目上有多个开发人员,则希望所有这些都在依赖项的同一版本上。您的依赖项也可能有自己的依赖性,并且您希望确保一切顺利。当您使用不同版本的相同依赖项时,它会产生甚至欺骗者。这通常是​​ CI​​ 环境中的情况。

Go 社区针对这些问题提出了许多不同的解决方案。但对我来说,没有一个是真正好的,所以在​​ Splice​​​ 我们找到了最简单的工作解决方案:​​https://github.com/pote/gpm​

Gpm 是一个简单的 bash 脚本,我们最终对其进行了​​一些修改​​,以便我们可以将脚本放到每个 repo 中。 bash 脚本使用名为 Godeps 的自定义文件,其中列出了要安装的软件包。

​当切换到不同的项目时,我们运行项目 gpm 脚本来下拉或设置每个包的正确版本。

在我们的 CI 环境中,我们在运行测试套件之前将 GOPATH 设置为项目特定的文件夹,因此项目之间不会共享包。

善用错误

错误是 Go 中非常重要的模式,起初,新开发人员对返回值和错误的函数数量感到惊讶。

Go 没有您可能在其他编程语言中看到的异常概念。 Go 确实有一种叫做 ​​panic​​ 的东西,但正如它的名字所暗示的那样,它们真的很特别,不应该被拯救(也就是说,它们可以)。

首先,Go的错误处理似乎繁琐和重复,但迅速成为我们思考方式的一部分。而不是创建泡起来且可能或可能不会处理或通过更高的异常,而是错误是响应的一部分,并且旨在由呼叫者处理。每当函数可能会生成错误时,其响应应包含错误参数。

Go 团队的 ​​Andrew Gerrand​​​ 写了一篇关于错误的很棒的​​博客文章​​,我强烈建议你阅读它。

​Effective Go section on errors​

翻译:​​http://www.golangbootcamp.com/book/tricks_and_tips#sec-using_errors​